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 "llvm/Support/WithColor.h" 250b57cec5SDimitry Andric #include <algorithm> 260b57cec5SDimitry Andric #include <cassert> 270b57cec5SDimitry Andric #include <cstddef> 280b57cec5SDimitry Andric #include <cstdint> 290b57cec5SDimitry Andric #include <cstdio> 300b57cec5SDimitry Andric #include <utility> 310b57cec5SDimitry Andric #include <vector> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric using namespace dwarf; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForSection(DWARFContext &C, 370b57cec5SDimitry Andric const DWARFSection &Section, 380b57cec5SDimitry Andric DWARFSectionKind SectionKind) { 390b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 400b57cec5SDimitry Andric addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(), 410b57cec5SDimitry Andric &D.getLocSection(), D.getStringSection(), 420b57cec5SDimitry Andric D.getStringOffsetSection(), &D.getAddrSection(), 430b57cec5SDimitry Andric D.getLineSection(), D.isLittleEndian(), false, false, 440b57cec5SDimitry Andric SectionKind); 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, 480b57cec5SDimitry Andric const DWARFSection &DWOSection, 490b57cec5SDimitry Andric DWARFSectionKind SectionKind, 500b57cec5SDimitry Andric bool Lazy) { 510b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 520b57cec5SDimitry Andric addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), 530b57cec5SDimitry Andric &D.getLocDWOSection(), D.getStringDWOSection(), 540b57cec5SDimitry Andric D.getStringOffsetDWOSection(), &D.getAddrSection(), 550b57cec5SDimitry Andric D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, 560b57cec5SDimitry Andric SectionKind); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric void DWARFUnitVector::addUnitsImpl( 600b57cec5SDimitry Andric DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, 610b57cec5SDimitry Andric const DWARFDebugAbbrev *DA, const DWARFSection *RS, 620b57cec5SDimitry Andric const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, 630b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, 640b57cec5SDimitry Andric bool Lazy, DWARFSectionKind SectionKind) { 650b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, Section, LE, 0); 660b57cec5SDimitry Andric // Lazy initialization of Parser, now that we have all section info. 670b57cec5SDimitry Andric if (!Parser) { 680b57cec5SDimitry Andric Parser = [=, &Context, &Obj, &Section, &SOS, 690b57cec5SDimitry Andric &LS](uint32_t Offset, DWARFSectionKind SectionKind, 700b57cec5SDimitry Andric const DWARFSection *CurSection, 710b57cec5SDimitry Andric const DWARFUnitIndex::Entry *IndexEntry) 720b57cec5SDimitry Andric -> std::unique_ptr<DWARFUnit> { 730b57cec5SDimitry Andric const DWARFSection &InfoSection = CurSection ? *CurSection : Section; 740b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, InfoSection, LE, 0); 750b57cec5SDimitry Andric if (!Data.isValidOffset(Offset)) 760b57cec5SDimitry Andric return nullptr; 770b57cec5SDimitry Andric const DWARFUnitIndex *Index = nullptr; 780b57cec5SDimitry Andric if (IsDWO) 790b57cec5SDimitry Andric Index = &getDWARFUnitIndex(Context, SectionKind); 800b57cec5SDimitry Andric DWARFUnitHeader Header; 810b57cec5SDimitry Andric if (!Header.extract(Context, Data, &Offset, SectionKind, Index, 820b57cec5SDimitry Andric IndexEntry)) 830b57cec5SDimitry Andric return nullptr; 840b57cec5SDimitry Andric std::unique_ptr<DWARFUnit> U; 850b57cec5SDimitry Andric if (Header.isTypeUnit()) 860b57cec5SDimitry Andric U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, 870b57cec5SDimitry Andric RS, LocSection, SS, SOS, AOS, LS, 880b57cec5SDimitry Andric LE, IsDWO, *this); 890b57cec5SDimitry Andric else 900b57cec5SDimitry Andric U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, 910b57cec5SDimitry Andric DA, RS, LocSection, SS, SOS, 920b57cec5SDimitry Andric AOS, LS, LE, IsDWO, *this); 930b57cec5SDimitry Andric return U; 940b57cec5SDimitry Andric }; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric if (Lazy) 970b57cec5SDimitry Andric return; 980b57cec5SDimitry Andric // Find a reasonable insertion point within the vector. We skip over 990b57cec5SDimitry Andric // (a) units from a different section, (b) units from the same section 1000b57cec5SDimitry Andric // but with lower offset-within-section. This keeps units in order 1010b57cec5SDimitry Andric // within a section, although not necessarily within the object file, 1020b57cec5SDimitry Andric // even if we do lazy parsing. 1030b57cec5SDimitry Andric auto I = this->begin(); 1040b57cec5SDimitry Andric uint32_t Offset = 0; 1050b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 1060b57cec5SDimitry Andric if (I != this->end() && 1070b57cec5SDimitry Andric (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { 1080b57cec5SDimitry Andric ++I; 1090b57cec5SDimitry Andric continue; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric auto U = Parser(Offset, SectionKind, &Section, nullptr); 1120b57cec5SDimitry Andric // If parsing failed, we're done with this section. 1130b57cec5SDimitry Andric if (!U) 1140b57cec5SDimitry Andric break; 1150b57cec5SDimitry Andric Offset = U->getNextUnitOffset(); 1160b57cec5SDimitry Andric I = std::next(this->insert(I, std::move(U))); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { 1210b57cec5SDimitry Andric auto I = std::upper_bound(begin(), end(), Unit, 1220b57cec5SDimitry Andric [](const std::unique_ptr<DWARFUnit> &LHS, 1230b57cec5SDimitry Andric const std::unique_ptr<DWARFUnit> &RHS) { 1240b57cec5SDimitry Andric return LHS->getOffset() < RHS->getOffset(); 1250b57cec5SDimitry Andric }); 1260b57cec5SDimitry Andric return this->insert(I, std::move(Unit))->get(); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const { 1300b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1310b57cec5SDimitry Andric auto *CU = 1320b57cec5SDimitry Andric std::upper_bound(begin(), end, Offset, 1330b57cec5SDimitry Andric [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1340b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1350b57cec5SDimitry Andric }); 1360b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1370b57cec5SDimitry Andric return CU->get(); 1380b57cec5SDimitry Andric return nullptr; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric DWARFUnit * 1420b57cec5SDimitry Andric DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { 1430b57cec5SDimitry Andric const auto *CUOff = E.getOffset(DW_SECT_INFO); 1440b57cec5SDimitry Andric if (!CUOff) 1450b57cec5SDimitry Andric return nullptr; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric auto Offset = CUOff->Offset; 1480b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric auto *CU = 1510b57cec5SDimitry Andric std::upper_bound(begin(), end, CUOff->Offset, 1520b57cec5SDimitry Andric [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1530b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1540b57cec5SDimitry Andric }); 1550b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1560b57cec5SDimitry Andric return CU->get(); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric if (!Parser) 1590b57cec5SDimitry Andric return nullptr; 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E); 1620b57cec5SDimitry Andric if (!U) 1630b57cec5SDimitry Andric U = nullptr; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric auto *NewCU = U.get(); 1660b57cec5SDimitry Andric this->insert(CU, std::move(U)); 1670b57cec5SDimitry Andric ++NumInfoUnits; 1680b57cec5SDimitry Andric return NewCU; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, 1720b57cec5SDimitry Andric const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, 1730b57cec5SDimitry Andric const DWARFSection *RS, const DWARFSection *LocSection, 1740b57cec5SDimitry Andric StringRef SS, const DWARFSection &SOS, 1750b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, 1760b57cec5SDimitry Andric bool IsDWO, const DWARFUnitVector &UnitVector) 1770b57cec5SDimitry Andric : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), 1780b57cec5SDimitry Andric RangeSection(RS), LocSection(LocSection), LineSection(LS), 1790b57cec5SDimitry Andric StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), 1800b57cec5SDimitry Andric isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { 1810b57cec5SDimitry Andric clear(); 1820b57cec5SDimitry Andric // For split DWARF we only need to keep track of the location list section's 1830b57cec5SDimitry Andric // data (no relocations), and if we are reading a package file, we need to 1840b57cec5SDimitry Andric // adjust the location list data based on the index entries. 1850b57cec5SDimitry Andric if (IsDWO) { 1860b57cec5SDimitry Andric LocSectionData = LocSection->Data; 1870b57cec5SDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 1880b57cec5SDimitry Andric if (const auto *C = IndexEntry->getOffset(DW_SECT_LOC)) 1890b57cec5SDimitry Andric LocSectionData = LocSectionData.substr(C->Offset, C->Length); 1900b57cec5SDimitry Andric } 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric DWARFUnit::~DWARFUnit() = default; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { 1960b57cec5SDimitry Andric return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, 1970b57cec5SDimitry Andric getAddressByteSize()); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric Optional<object::SectionedAddress> 2010b57cec5SDimitry Andric DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { 2020b57cec5SDimitry Andric if (IsDWO) { 2030b57cec5SDimitry Andric auto R = Context.info_section_units(); 2040b57cec5SDimitry Andric auto I = R.begin(); 2050b57cec5SDimitry Andric // Surprising if a DWO file has more than one skeleton unit in it - this 2060b57cec5SDimitry Andric // probably shouldn't be valid, but if a use case is found, here's where to 2070b57cec5SDimitry Andric // support it (probably have to linearly search for the matching skeleton CU 2080b57cec5SDimitry Andric // here) 2090b57cec5SDimitry Andric if (I != R.end() && std::next(I) == R.end()) 2100b57cec5SDimitry Andric return (*I)->getAddrOffsetSectionItem(Index); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); 2130b57cec5SDimitry Andric if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) 2140b57cec5SDimitry Andric return None; 2150b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, 2160b57cec5SDimitry Andric isLittleEndian, getAddressByteSize()); 2170b57cec5SDimitry Andric uint64_t Section; 2180b57cec5SDimitry Andric uint64_t Address = DA.getRelocatedAddress(&Offset, &Section); 2190b57cec5SDimitry Andric return {{Address, Section}}; 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { 2230b57cec5SDimitry Andric if (!StringOffsetsTableContribution) 2240b57cec5SDimitry Andric return None; 2250b57cec5SDimitry Andric unsigned ItemSize = getDwarfStringOffsetsByteSize(); 2260b57cec5SDimitry Andric uint32_t Offset = getStringOffsetsBase() + Index * ItemSize; 2270b57cec5SDimitry Andric if (StringOffsetSection.Data.size() < Offset + ItemSize) 2280b57cec5SDimitry Andric return None; 2290b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 2300b57cec5SDimitry Andric isLittleEndian, 0); 2310b57cec5SDimitry Andric return DA.getRelocatedValue(ItemSize, &Offset); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric bool DWARFUnitHeader::extract(DWARFContext &Context, 2350b57cec5SDimitry Andric const DWARFDataExtractor &debug_info, 2360b57cec5SDimitry Andric uint32_t *offset_ptr, 2370b57cec5SDimitry Andric DWARFSectionKind SectionKind, 2380b57cec5SDimitry Andric const DWARFUnitIndex *Index, 2390b57cec5SDimitry Andric const DWARFUnitIndex::Entry *Entry) { 2400b57cec5SDimitry Andric Offset = *offset_ptr; 2410b57cec5SDimitry Andric IndexEntry = Entry; 2420b57cec5SDimitry Andric if (!IndexEntry && Index) 2430b57cec5SDimitry Andric IndexEntry = Index->getFromOffset(*offset_ptr); 2440b57cec5SDimitry Andric Length = debug_info.getRelocatedValue(4, offset_ptr); 2450b57cec5SDimitry Andric FormParams.Format = DWARF32; 2460b57cec5SDimitry Andric unsigned SizeOfLength = 4; 2470b57cec5SDimitry Andric if (Length == 0xffffffff) { 2480b57cec5SDimitry Andric Length = debug_info.getU64(offset_ptr); 2490b57cec5SDimitry Andric FormParams.Format = DWARF64; 2500b57cec5SDimitry Andric SizeOfLength = 8; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric FormParams.Version = debug_info.getU16(offset_ptr); 2530b57cec5SDimitry Andric if (FormParams.Version >= 5) { 2540b57cec5SDimitry Andric UnitType = debug_info.getU8(offset_ptr); 2550b57cec5SDimitry Andric FormParams.AddrSize = debug_info.getU8(offset_ptr); 2560b57cec5SDimitry Andric AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); 2570b57cec5SDimitry Andric } else { 2580b57cec5SDimitry Andric AbbrOffset = debug_info.getRelocatedValue(FormParams.getDwarfOffsetByteSize(), offset_ptr); 2590b57cec5SDimitry Andric FormParams.AddrSize = debug_info.getU8(offset_ptr); 2600b57cec5SDimitry Andric // Fake a unit type based on the section type. This isn't perfect, 2610b57cec5SDimitry Andric // but distinguishing compile and type units is generally enough. 2620b57cec5SDimitry Andric if (SectionKind == DW_SECT_TYPES) 2630b57cec5SDimitry Andric UnitType = DW_UT_type; 2640b57cec5SDimitry Andric else 2650b57cec5SDimitry Andric UnitType = DW_UT_compile; 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric if (IndexEntry) { 2680b57cec5SDimitry Andric if (AbbrOffset) 2690b57cec5SDimitry Andric return false; 2700b57cec5SDimitry Andric auto *UnitContrib = IndexEntry->getOffset(); 2710b57cec5SDimitry Andric if (!UnitContrib || UnitContrib->Length != (Length + 4)) 2720b57cec5SDimitry Andric return false; 2730b57cec5SDimitry Andric auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV); 2740b57cec5SDimitry Andric if (!AbbrEntry) 2750b57cec5SDimitry Andric return false; 2760b57cec5SDimitry Andric AbbrOffset = AbbrEntry->Offset; 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric if (isTypeUnit()) { 2790b57cec5SDimitry Andric TypeHash = debug_info.getU64(offset_ptr); 2800b57cec5SDimitry Andric TypeOffset = debug_info.getU32(offset_ptr); 2810b57cec5SDimitry Andric } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) 2820b57cec5SDimitry Andric DWOId = debug_info.getU64(offset_ptr); 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric // Header fields all parsed, capture the size of this unit header. 2850b57cec5SDimitry Andric assert(*offset_ptr - Offset <= 255 && "unexpected header size"); 2860b57cec5SDimitry Andric Size = uint8_t(*offset_ptr - Offset); 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric // Type offset is unit-relative; should be after the header and before 2890b57cec5SDimitry Andric // the end of the current unit. 2900b57cec5SDimitry Andric bool TypeOffsetOK = 2910b57cec5SDimitry Andric !isTypeUnit() 2920b57cec5SDimitry Andric ? true 2930b57cec5SDimitry Andric : TypeOffset >= Size && TypeOffset < getLength() + SizeOfLength; 2940b57cec5SDimitry Andric bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 2950b57cec5SDimitry Andric bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); 2960b57cec5SDimitry Andric bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK) 2990b57cec5SDimitry Andric return false; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // Keep track of the highest DWARF version we encounter across all units. 3020b57cec5SDimitry Andric Context.setMaxVersionIfGreater(getVersion()); 3030b57cec5SDimitry Andric return true; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric // Parse the rangelist table header, including the optional array of offsets 3070b57cec5SDimitry Andric // following it (DWARF v5 and later). 3080b57cec5SDimitry Andric static Expected<DWARFDebugRnglistTable> 3090b57cec5SDimitry Andric parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { 3100b57cec5SDimitry Andric // TODO: Support DWARF64 3110b57cec5SDimitry Andric // We are expected to be called with Offset 0 or pointing just past the table 3120b57cec5SDimitry Andric // header, which is 12 bytes long for DWARF32. 3130b57cec5SDimitry Andric if (Offset > 0) { 3140b57cec5SDimitry Andric if (Offset < 12U) 3150b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "Did not detect a valid" 3160b57cec5SDimitry Andric " range list table with base = 0x%" PRIu32, 3170b57cec5SDimitry Andric Offset); 3180b57cec5SDimitry Andric Offset -= 12U; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric llvm::DWARFDebugRnglistTable Table; 3210b57cec5SDimitry Andric if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) 3220b57cec5SDimitry Andric return std::move(E); 3230b57cec5SDimitry Andric return Table; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric Error DWARFUnit::extractRangeList(uint32_t RangeListOffset, 3270b57cec5SDimitry Andric DWARFDebugRangeList &RangeList) const { 3280b57cec5SDimitry Andric // Require that compile unit is extracted. 3290b57cec5SDimitry Andric assert(!DieArray.empty()); 3300b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 3310b57cec5SDimitry Andric isLittleEndian, getAddressByteSize()); 3320b57cec5SDimitry Andric uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 3330b57cec5SDimitry Andric return RangeList.extract(RangesData, &ActualRangeListOffset); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric void DWARFUnit::clear() { 3370b57cec5SDimitry Andric Abbrevs = nullptr; 3380b57cec5SDimitry Andric BaseAddr.reset(); 3390b57cec5SDimitry Andric RangeSectionBase = 0; 3400b57cec5SDimitry Andric AddrOffsetSectionBase = 0; 3410b57cec5SDimitry Andric clearDIEs(false); 3420b57cec5SDimitry Andric DWO.reset(); 3430b57cec5SDimitry Andric } 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric const char *DWARFUnit::getCompilationDir() { 3460b57cec5SDimitry Andric return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric void DWARFUnit::extractDIEsToVector( 3500b57cec5SDimitry Andric bool AppendCUDie, bool AppendNonCUDies, 3510b57cec5SDimitry Andric std::vector<DWARFDebugInfoEntry> &Dies) const { 3520b57cec5SDimitry Andric if (!AppendCUDie && !AppendNonCUDies) 3530b57cec5SDimitry Andric return; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric // Set the offset to that of the first DIE and calculate the start of the 3560b57cec5SDimitry Andric // next compilation unit header. 3570b57cec5SDimitry Andric uint32_t DIEOffset = getOffset() + getHeaderSize(); 3580b57cec5SDimitry Andric uint32_t NextCUOffset = getNextUnitOffset(); 3590b57cec5SDimitry Andric DWARFDebugInfoEntry DIE; 3600b57cec5SDimitry Andric DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); 3610b57cec5SDimitry Andric uint32_t Depth = 0; 3620b57cec5SDimitry Andric bool IsCUDie = true; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, 3650b57cec5SDimitry Andric Depth)) { 3660b57cec5SDimitry Andric if (IsCUDie) { 3670b57cec5SDimitry Andric if (AppendCUDie) 3680b57cec5SDimitry Andric Dies.push_back(DIE); 3690b57cec5SDimitry Andric if (!AppendNonCUDies) 3700b57cec5SDimitry Andric break; 3710b57cec5SDimitry Andric // The average bytes per DIE entry has been seen to be 3720b57cec5SDimitry Andric // around 14-20 so let's pre-reserve the needed memory for 3730b57cec5SDimitry Andric // our DIE entries accordingly. 3740b57cec5SDimitry Andric Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 3750b57cec5SDimitry Andric IsCUDie = false; 3760b57cec5SDimitry Andric } else { 3770b57cec5SDimitry Andric Dies.push_back(DIE); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric if (const DWARFAbbreviationDeclaration *AbbrDecl = 3810b57cec5SDimitry Andric DIE.getAbbreviationDeclarationPtr()) { 3820b57cec5SDimitry Andric // Normal DIE 3830b57cec5SDimitry Andric if (AbbrDecl->hasChildren()) 3840b57cec5SDimitry Andric ++Depth; 3850b57cec5SDimitry Andric } else { 3860b57cec5SDimitry Andric // NULL DIE. 3870b57cec5SDimitry Andric if (Depth > 0) 3880b57cec5SDimitry Andric --Depth; 3890b57cec5SDimitry Andric if (Depth == 0) 3900b57cec5SDimitry Andric break; // We are done with this compile unit! 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric // Give a little bit of info if we encounter corrupt DWARF (our offset 3950b57cec5SDimitry Andric // should always terminate at or before the start of the next compilation 3960b57cec5SDimitry Andric // unit header). 3970b57cec5SDimitry Andric if (DIEOffset > NextCUOffset) 3980b57cec5SDimitry Andric WithColor::warning() << format("DWARF compile unit extends beyond its " 3990b57cec5SDimitry Andric "bounds cu 0x%8.8x at 0x%8.8x\n", 4000b57cec5SDimitry Andric getOffset(), DIEOffset); 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 4040b57cec5SDimitry Andric if ((CUDieOnly && !DieArray.empty()) || 4050b57cec5SDimitry Andric DieArray.size() > 1) 4060b57cec5SDimitry Andric return 0; // Already parsed. 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric bool HasCUDie = !DieArray.empty(); 4090b57cec5SDimitry Andric extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric if (DieArray.empty()) 4120b57cec5SDimitry Andric return 0; 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric // If CU DIE was just parsed, copy several attribute values from it. 4150b57cec5SDimitry Andric if (!HasCUDie) { 4160b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 4170b57cec5SDimitry Andric if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) 4180b57cec5SDimitry Andric Header.setDWOId(*DWOId); 4190b57cec5SDimitry Andric if (!IsDWO) { 4200b57cec5SDimitry Andric assert(AddrOffsetSectionBase == 0); 4210b57cec5SDimitry Andric assert(RangeSectionBase == 0); 4220b57cec5SDimitry Andric AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base), 0); 4230b57cec5SDimitry Andric if (!AddrOffsetSectionBase) 4240b57cec5SDimitry Andric AddrOffsetSectionBase = 4250b57cec5SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); 4260b57cec5SDimitry Andric RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // In general, in DWARF v5 and beyond we derive the start of the unit's 4300b57cec5SDimitry Andric // contribution to the string offsets table from the unit DIE's 4310b57cec5SDimitry Andric // DW_AT_str_offsets_base attribute. Split DWARF units do not use this 4320b57cec5SDimitry Andric // attribute, so we assume that there is a contribution to the string 4330b57cec5SDimitry Andric // offsets table starting at offset 0 of the debug_str_offsets.dwo section. 4340b57cec5SDimitry Andric // In both cases we need to determine the format of the contribution, 4350b57cec5SDimitry Andric // which may differ from the unit's format. 4360b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 4370b57cec5SDimitry Andric isLittleEndian, 0); 4380b57cec5SDimitry Andric if (IsDWO || getVersion() >= 5) { 4390b57cec5SDimitry Andric auto StringOffsetOrError = 4400b57cec5SDimitry Andric IsDWO ? determineStringOffsetsTableContributionDWO(DA) 4410b57cec5SDimitry Andric : determineStringOffsetsTableContribution(DA); 4420b57cec5SDimitry Andric if (!StringOffsetOrError) { 4430b57cec5SDimitry Andric WithColor::error() << "invalid contribution to string offsets table in section .debug_str_offsets[.dwo]: " 4440b57cec5SDimitry Andric << toString(StringOffsetOrError.takeError()) << '\n'; 4450b57cec5SDimitry Andric } else { 4460b57cec5SDimitry Andric StringOffsetsTableContribution = *StringOffsetOrError; 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to 4510b57cec5SDimitry Andric // describe address ranges. 4520b57cec5SDimitry Andric if (getVersion() >= 5) { 4530b57cec5SDimitry Andric if (IsDWO) 4540b57cec5SDimitry Andric setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); 4550b57cec5SDimitry Andric else 4560b57cec5SDimitry Andric setRangesSection(&Context.getDWARFObj().getRnglistsSection(), 4570b57cec5SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); 4580b57cec5SDimitry Andric if (RangeSection->Data.size()) { 4590b57cec5SDimitry Andric // Parse the range list table header. Individual range lists are 4600b57cec5SDimitry Andric // extracted lazily. 4610b57cec5SDimitry Andric DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, 4620b57cec5SDimitry Andric isLittleEndian, 0); 4630b57cec5SDimitry Andric if (auto TableOrError = 4640b57cec5SDimitry Andric parseRngListTableHeader(RangesDA, RangeSectionBase)) 4650b57cec5SDimitry Andric RngListTable = TableOrError.get(); 4660b57cec5SDimitry Andric else 4670b57cec5SDimitry Andric WithColor::error() << "parsing a range list table: " 4680b57cec5SDimitry Andric << toString(TableOrError.takeError()) 4690b57cec5SDimitry Andric << '\n'; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. 4720b57cec5SDimitry Andric // Adjust RangeSectionBase to point past the table header. 4730b57cec5SDimitry Andric if (IsDWO && RngListTable) 4740b57cec5SDimitry Andric RangeSectionBase = RngListTable->getHeaderSize(); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 4790b57cec5SDimitry Andric // skeleton CU DIE, so that DWARF users not aware of it are not broken. 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric return DieArray.size(); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric bool DWARFUnit::parseDWO() { 4860b57cec5SDimitry Andric if (IsDWO) 4870b57cec5SDimitry Andric return false; 4880b57cec5SDimitry Andric if (DWO.get()) 4890b57cec5SDimitry Andric return false; 4900b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 4910b57cec5SDimitry Andric if (!UnitDie) 4920b57cec5SDimitry Andric return false; 4930b57cec5SDimitry Andric auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); 4940b57cec5SDimitry Andric if (!DWOFileName) 4950b57cec5SDimitry Andric return false; 4960b57cec5SDimitry Andric auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); 4970b57cec5SDimitry Andric SmallString<16> AbsolutePath; 4980b57cec5SDimitry Andric if (sys::path::is_relative(*DWOFileName) && CompilationDir && 4990b57cec5SDimitry Andric *CompilationDir) { 5000b57cec5SDimitry Andric sys::path::append(AbsolutePath, *CompilationDir); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric sys::path::append(AbsolutePath, *DWOFileName); 5030b57cec5SDimitry Andric auto DWOId = getDWOId(); 5040b57cec5SDimitry Andric if (!DWOId) 5050b57cec5SDimitry Andric return false; 5060b57cec5SDimitry Andric auto DWOContext = Context.getDWOContext(AbsolutePath); 5070b57cec5SDimitry Andric if (!DWOContext) 5080b57cec5SDimitry Andric return false; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); 5110b57cec5SDimitry Andric if (!DWOCU) 5120b57cec5SDimitry Andric return false; 5130b57cec5SDimitry Andric DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); 5140b57cec5SDimitry Andric // Share .debug_addr and .debug_ranges section with compile unit in .dwo 5150b57cec5SDimitry Andric DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 5160b57cec5SDimitry Andric if (getVersion() >= 5) { 5170b57cec5SDimitry Andric DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); 5180b57cec5SDimitry Andric DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, 5190b57cec5SDimitry Andric isLittleEndian, 0); 5200b57cec5SDimitry Andric if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase)) 5210b57cec5SDimitry Andric DWO->RngListTable = TableOrError.get(); 5220b57cec5SDimitry Andric else 5230b57cec5SDimitry Andric WithColor::error() << "parsing a range list table: " 5240b57cec5SDimitry Andric << toString(TableOrError.takeError()) 5250b57cec5SDimitry Andric << '\n'; 5260b57cec5SDimitry Andric if (DWO->RngListTable) 5270b57cec5SDimitry Andric DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); 5280b57cec5SDimitry Andric } else { 5290b57cec5SDimitry Andric auto DWORangesBase = UnitDie.getRangesBaseAttribute(); 5300b57cec5SDimitry Andric DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric return true; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric void DWARFUnit::clearDIEs(bool KeepCUDie) { 5370b57cec5SDimitry Andric if (DieArray.size() > (unsigned)KeepCUDie) { 5380b57cec5SDimitry Andric DieArray.resize((unsigned)KeepCUDie); 5390b57cec5SDimitry Andric DieArray.shrink_to_fit(); 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 5440b57cec5SDimitry Andric DWARFUnit::findRnglistFromOffset(uint32_t Offset) { 5450b57cec5SDimitry Andric if (getVersion() <= 4) { 5460b57cec5SDimitry Andric DWARFDebugRangeList RangeList; 5470b57cec5SDimitry Andric if (Error E = extractRangeList(Offset, RangeList)) 5480b57cec5SDimitry Andric return std::move(E); 5490b57cec5SDimitry Andric return RangeList.getAbsoluteRanges(getBaseAddress()); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric if (RngListTable) { 5520b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 5530b57cec5SDimitry Andric isLittleEndian, RngListTable->getAddrSize()); 5540b57cec5SDimitry Andric auto RangeListOrError = RngListTable->findList(RangesData, Offset); 5550b57cec5SDimitry Andric if (RangeListOrError) 5560b57cec5SDimitry Andric return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); 5570b57cec5SDimitry Andric return RangeListOrError.takeError(); 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 5610b57cec5SDimitry Andric "missing or invalid range list table"); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 5650b57cec5SDimitry Andric DWARFUnit::findRnglistFromIndex(uint32_t Index) { 5660b57cec5SDimitry Andric if (auto Offset = getRnglistOffset(Index)) 5670b57cec5SDimitry Andric return findRnglistFromOffset(*Offset + RangeSectionBase); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric if (RngListTable) 5700b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 5710b57cec5SDimitry Andric "invalid range list table index %d", Index); 5720b57cec5SDimitry Andric else 5730b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 5740b57cec5SDimitry Andric "missing or invalid range list table"); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { 5780b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 5790b57cec5SDimitry Andric if (!UnitDie) 5800b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "No unit DIE"); 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric // First, check if unit DIE describes address ranges for the whole unit. 5830b57cec5SDimitry Andric auto CUDIERangesOrError = UnitDie.getAddressRanges(); 5840b57cec5SDimitry Andric if (!CUDIERangesOrError) 5850b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 5860b57cec5SDimitry Andric "decoding address ranges: %s", 5870b57cec5SDimitry Andric toString(CUDIERangesOrError.takeError()).c_str()); 5880b57cec5SDimitry Andric return *CUDIERangesOrError; 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric void DWARFUnit::updateAddressDieMap(DWARFDie Die) { 5920b57cec5SDimitry Andric if (Die.isSubroutineDIE()) { 5930b57cec5SDimitry Andric auto DIERangesOrError = Die.getAddressRanges(); 5940b57cec5SDimitry Andric if (DIERangesOrError) { 5950b57cec5SDimitry Andric for (const auto &R : DIERangesOrError.get()) { 5960b57cec5SDimitry Andric // Ignore 0-sized ranges. 5970b57cec5SDimitry Andric if (R.LowPC == R.HighPC) 5980b57cec5SDimitry Andric continue; 5990b57cec5SDimitry Andric auto B = AddrDieMap.upper_bound(R.LowPC); 6000b57cec5SDimitry Andric if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { 6010b57cec5SDimitry Andric // The range is a sub-range of existing ranges, we need to split the 6020b57cec5SDimitry Andric // existing range. 6030b57cec5SDimitry Andric if (R.HighPC < B->second.first) 6040b57cec5SDimitry Andric AddrDieMap[R.HighPC] = B->second; 6050b57cec5SDimitry Andric if (R.LowPC > B->first) 6060b57cec5SDimitry Andric AddrDieMap[B->first].first = R.LowPC; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric } else 6110b57cec5SDimitry Andric llvm::consumeError(DIERangesOrError.takeError()); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to 6140b57cec5SDimitry Andric // simplify the logic to update AddrDieMap. The child's range will always 6150b57cec5SDimitry Andric // be equal or smaller than the parent's range. With this assumption, when 6160b57cec5SDimitry Andric // adding one range into the map, it will at most split a range into 3 6170b57cec5SDimitry Andric // sub-ranges. 6180b57cec5SDimitry Andric for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) 6190b57cec5SDimitry Andric updateAddressDieMap(Child); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { 6230b57cec5SDimitry Andric extractDIEsIfNeeded(false); 6240b57cec5SDimitry Andric if (AddrDieMap.empty()) 6250b57cec5SDimitry Andric updateAddressDieMap(getUnitDIE()); 6260b57cec5SDimitry Andric auto R = AddrDieMap.upper_bound(Address); 6270b57cec5SDimitry Andric if (R == AddrDieMap.begin()) 6280b57cec5SDimitry Andric return DWARFDie(); 6290b57cec5SDimitry Andric // upper_bound's previous item contains Address. 6300b57cec5SDimitry Andric --R; 6310b57cec5SDimitry Andric if (Address >= R->second.first) 6320b57cec5SDimitry Andric return DWARFDie(); 6330b57cec5SDimitry Andric return R->second.second; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric void 6370b57cec5SDimitry Andric DWARFUnit::getInlinedChainForAddress(uint64_t Address, 6380b57cec5SDimitry Andric SmallVectorImpl<DWARFDie> &InlinedChain) { 6390b57cec5SDimitry Andric assert(InlinedChain.empty()); 6400b57cec5SDimitry Andric // Try to look for subprogram DIEs in the DWO file. 6410b57cec5SDimitry Andric parseDWO(); 6420b57cec5SDimitry Andric // First, find the subroutine that contains the given address (the leaf 6430b57cec5SDimitry Andric // of inlined chain). 6440b57cec5SDimitry Andric DWARFDie SubroutineDIE = 6450b57cec5SDimitry Andric (DWO ? *DWO : *this).getSubroutineForAddress(Address); 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric if (!SubroutineDIE) 6480b57cec5SDimitry Andric return; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric while (!SubroutineDIE.isSubprogramDIE()) { 6510b57cec5SDimitry Andric if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine) 6520b57cec5SDimitry Andric InlinedChain.push_back(SubroutineDIE); 6530b57cec5SDimitry Andric SubroutineDIE = SubroutineDIE.getParent(); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric InlinedChain.push_back(SubroutineDIE); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, 6590b57cec5SDimitry Andric DWARFSectionKind Kind) { 6600b57cec5SDimitry Andric if (Kind == DW_SECT_INFO) 6610b57cec5SDimitry Andric return Context.getCUIndex(); 6620b57cec5SDimitry Andric assert(Kind == DW_SECT_TYPES); 6630b57cec5SDimitry Andric return Context.getTUIndex(); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { 6670b57cec5SDimitry Andric if (!Die) 6680b57cec5SDimitry Andric return DWARFDie(); 6690b57cec5SDimitry Andric const uint32_t Depth = Die->getDepth(); 6700b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have parents. 6710b57cec5SDimitry Andric if (Depth == 0) 6720b57cec5SDimitry Andric return DWARFDie(); 6730b57cec5SDimitry Andric // Depth of 1 always means parent is the compile/type unit. 6740b57cec5SDimitry Andric if (Depth == 1) 6750b57cec5SDimitry Andric return getUnitDIE(); 6760b57cec5SDimitry Andric // Look for previous DIE with a depth that is one less than the Die's depth. 6770b57cec5SDimitry Andric const uint32_t ParentDepth = Depth - 1; 6780b57cec5SDimitry Andric for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) { 6790b57cec5SDimitry Andric if (DieArray[I].getDepth() == ParentDepth) 6800b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric return DWARFDie(); 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { 6860b57cec5SDimitry Andric if (!Die) 6870b57cec5SDimitry Andric return DWARFDie(); 6880b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 6890b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have siblings. 6900b57cec5SDimitry Andric if (Depth == 0) 6910b57cec5SDimitry Andric return DWARFDie(); 6920b57cec5SDimitry Andric // NULL DIEs don't have siblings. 6930b57cec5SDimitry Andric if (Die->getAbbreviationDeclarationPtr() == nullptr) 6940b57cec5SDimitry Andric return DWARFDie(); 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric // Find the next DIE whose depth is the same as the Die's depth. 6970b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx; 6980b57cec5SDimitry Andric ++I) { 6990b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth) 7000b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric return DWARFDie(); 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { 7060b57cec5SDimitry Andric if (!Die) 7070b57cec5SDimitry Andric return DWARFDie(); 7080b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 7090b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have siblings. 7100b57cec5SDimitry Andric if (Depth == 0) 7110b57cec5SDimitry Andric return DWARFDie(); 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric // Find the previous DIE whose depth is the same as the Die's depth. 7140b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die); I > 0;) { 7150b57cec5SDimitry Andric --I; 7160b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth - 1) 7170b57cec5SDimitry Andric return DWARFDie(); 7180b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth) 7190b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric return DWARFDie(); 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { 7250b57cec5SDimitry Andric if (!Die->hasChildren()) 7260b57cec5SDimitry Andric return DWARFDie(); 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric // We do not want access out of bounds when parsing corrupted debug data. 7290b57cec5SDimitry Andric size_t I = getDIEIndex(Die) + 1; 7300b57cec5SDimitry Andric if (I >= DieArray.size()) 7310b57cec5SDimitry Andric return DWARFDie(); 7320b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { 7360b57cec5SDimitry Andric if (!Die->hasChildren()) 7370b57cec5SDimitry Andric return DWARFDie(); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 7400b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx; 7410b57cec5SDimitry Andric ++I) { 7420b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth + 1 && 7430b57cec5SDimitry Andric DieArray[I].getTag() == dwarf::DW_TAG_null) 7440b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 7450b57cec5SDimitry Andric assert(DieArray[I].getDepth() > Depth && "Not processing children?"); 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric return DWARFDie(); 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { 7510b57cec5SDimitry Andric if (!Abbrevs) 7520b57cec5SDimitry Andric Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset()); 7530b57cec5SDimitry Andric return Abbrevs; 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { 7570b57cec5SDimitry Andric if (BaseAddr) 7580b57cec5SDimitry Andric return BaseAddr; 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 7610b57cec5SDimitry Andric Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); 7620b57cec5SDimitry Andric BaseAddr = toSectionedAddress(PC); 7630b57cec5SDimitry Andric return BaseAddr; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric Expected<StrOffsetsContributionDescriptor> 7670b57cec5SDimitry Andric StrOffsetsContributionDescriptor::validateContributionSize( 7680b57cec5SDimitry Andric DWARFDataExtractor &DA) { 7690b57cec5SDimitry Andric uint8_t EntrySize = getDwarfOffsetByteSize(); 7700b57cec5SDimitry Andric // In order to ensure that we don't read a partial record at the end of 7710b57cec5SDimitry Andric // the section we validate for a multiple of the entry size. 7720b57cec5SDimitry Andric uint64_t ValidationSize = alignTo(Size, EntrySize); 7730b57cec5SDimitry Andric // Guard against overflow. 7740b57cec5SDimitry Andric if (ValidationSize >= Size) 7750b57cec5SDimitry Andric if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize)) 7760b57cec5SDimitry Andric return *this; 7770b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "length exceeds section size"); 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7800b57cec5SDimitry Andric // Look for a DWARF64-formatted contribution to the string offsets table 7810b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 7820b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 7830b57cec5SDimitry Andric parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { 7840b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 16)) 7850b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric if (DA.getU32(&Offset) != 0xffffffff) 7880b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit"); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric uint64_t Size = DA.getU64(&Offset); 7910b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 7920b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 7930b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 7940b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 7950b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64); 7960b57cec5SDimitry Andric } 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric // Look for a DWARF32-formatted contribution to the string offsets table 7990b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 8000b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 8010b57cec5SDimitry Andric parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) { 8020b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 8)) 8030b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric uint32_t ContributionSize = DA.getU32(&Offset); 8060b57cec5SDimitry Andric if (ContributionSize >= 0xfffffff0) 8070b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "invalid length"); 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 8100b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 8110b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 8120b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 8130b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version, 8140b57cec5SDimitry Andric DWARF32); 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 8180b57cec5SDimitry Andric parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, 8190b57cec5SDimitry Andric llvm::dwarf::DwarfFormat Format, 8200b57cec5SDimitry Andric uint64_t Offset) { 8210b57cec5SDimitry Andric StrOffsetsContributionDescriptor Desc; 8220b57cec5SDimitry Andric switch (Format) { 8230b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF64: { 8240b57cec5SDimitry Andric if (Offset < 16) 8250b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix"); 8260b57cec5SDimitry Andric auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16); 8270b57cec5SDimitry Andric if (!DescOrError) 8280b57cec5SDimitry Andric return DescOrError.takeError(); 8290b57cec5SDimitry Andric Desc = *DescOrError; 8300b57cec5SDimitry Andric break; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF32: { 8330b57cec5SDimitry Andric if (Offset < 8) 8340b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix"); 8350b57cec5SDimitry Andric auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8); 8360b57cec5SDimitry Andric if (!DescOrError) 8370b57cec5SDimitry Andric return DescOrError.takeError(); 8380b57cec5SDimitry Andric Desc = *DescOrError; 8390b57cec5SDimitry Andric break; 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric } 8420b57cec5SDimitry Andric return Desc.validateContributionSize(DA); 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric Expected<Optional<StrOffsetsContributionDescriptor>> 8460b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { 8470b57cec5SDimitry Andric uint64_t Offset; 8480b57cec5SDimitry Andric if (IsDWO) { 8490b57cec5SDimitry Andric Offset = 0; 8500b57cec5SDimitry Andric if (DA.getData().data() == nullptr) 8510b57cec5SDimitry Andric return None; 8520b57cec5SDimitry Andric } else { 8530b57cec5SDimitry Andric auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base)); 8540b57cec5SDimitry Andric if (!OptOffset) 8550b57cec5SDimitry Andric return None; 8560b57cec5SDimitry Andric Offset = *OptOffset; 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); 8590b57cec5SDimitry Andric if (!DescOrError) 8600b57cec5SDimitry Andric return DescOrError.takeError(); 8610b57cec5SDimitry Andric return *DescOrError; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric Expected<Optional<StrOffsetsContributionDescriptor>> 8650b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { 8660b57cec5SDimitry Andric uint64_t Offset = 0; 8670b57cec5SDimitry Andric auto IndexEntry = Header.getIndexEntry(); 8680b57cec5SDimitry Andric const auto *C = 8690b57cec5SDimitry Andric IndexEntry ? IndexEntry->getOffset(DW_SECT_STR_OFFSETS) : nullptr; 8700b57cec5SDimitry Andric if (C) 8710b57cec5SDimitry Andric Offset = C->Offset; 8720b57cec5SDimitry Andric if (getVersion() >= 5) { 8730b57cec5SDimitry Andric if (DA.getData().data() == nullptr) 8740b57cec5SDimitry Andric return None; 8750b57cec5SDimitry Andric Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16; 8760b57cec5SDimitry Andric // Look for a valid contribution at the given offset. 8770b57cec5SDimitry Andric auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); 8780b57cec5SDimitry Andric if (!DescOrError) 8790b57cec5SDimitry Andric return DescOrError.takeError(); 8800b57cec5SDimitry Andric return *DescOrError; 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric // Prior to DWARF v5, we derive the contribution size from the 8830b57cec5SDimitry Andric // index table (in a package file). In a .dwo file it is simply 8840b57cec5SDimitry Andric // the length of the string offsets section. 8850b57cec5SDimitry Andric if (!IndexEntry) 8860b57cec5SDimitry Andric return { 8870b57cec5SDimitry Andric Optional<StrOffsetsContributionDescriptor>( 8880b57cec5SDimitry Andric {0, StringOffsetSection.Data.size(), 4, DWARF32})}; 8890b57cec5SDimitry Andric if (C) 8900b57cec5SDimitry Andric return {Optional<StrOffsetsContributionDescriptor>( 8910b57cec5SDimitry Andric {C->Offset, C->Length, 4, DWARF32})}; 8920b57cec5SDimitry Andric return None; 8930b57cec5SDimitry Andric } 894