10b57cec5SDimitry Andric //===- DWARFUnit.h ----------------------------------------------*- C++ -*-===//
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 #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
100b57cec5SDimitry Andric #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
110b57cec5SDimitry Andric
1281ad6265SDimitry Andric #include "llvm/ADT/DenseSet.h"
130b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
160b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
1881ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
1981ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
200b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
210b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h"
2281ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
230b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
240b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h"
250b57cec5SDimitry Andric #include <cassert>
260b57cec5SDimitry Andric #include <cstddef>
270b57cec5SDimitry Andric #include <cstdint>
280b57cec5SDimitry Andric #include <map>
290b57cec5SDimitry Andric #include <memory>
3081ad6265SDimitry Andric #include <set>
310b57cec5SDimitry Andric #include <utility>
320b57cec5SDimitry Andric #include <vector>
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric namespace llvm {
350b57cec5SDimitry Andric
360b57cec5SDimitry Andric class DWARFAbbreviationDeclarationSet;
370b57cec5SDimitry Andric class DWARFContext;
380b57cec5SDimitry Andric class DWARFDebugAbbrev;
390b57cec5SDimitry Andric class DWARFUnit;
4081ad6265SDimitry Andric class DWARFDebugRangeList;
4181ad6265SDimitry Andric class DWARFLocationTable;
4281ad6265SDimitry Andric class DWARFObject;
4381ad6265SDimitry Andric class raw_ostream;
4481ad6265SDimitry Andric struct DIDumpOptions;
4581ad6265SDimitry Andric struct DWARFSection;
461db9f3b2SDimitry Andric namespace dwarf_linker {
471db9f3b2SDimitry Andric namespace parallel {
4806c3fb27SDimitry Andric class CompileUnit;
4906c3fb27SDimitry Andric }
501db9f3b2SDimitry Andric } // namespace dwarf_linker
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric /// Base class describing the header of any kind of "unit." Some information
530b57cec5SDimitry Andric /// is specific to certain unit types. We separate this class out so we can
540b57cec5SDimitry Andric /// parse the header before deciding what specific kind of unit to construct.
550b57cec5SDimitry Andric class DWARFUnitHeader {
560b57cec5SDimitry Andric // Offset within section.
578bcb0991SDimitry Andric uint64_t Offset = 0;
580b57cec5SDimitry Andric // Version, address size, and DWARF format.
590b57cec5SDimitry Andric dwarf::FormParams FormParams;
600b57cec5SDimitry Andric uint64_t Length = 0;
610b57cec5SDimitry Andric uint64_t AbbrOffset = 0;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric // For DWO units only.
640b57cec5SDimitry Andric const DWARFUnitIndex::Entry *IndexEntry = nullptr;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric // For type units only.
670b57cec5SDimitry Andric uint64_t TypeHash = 0;
688bcb0991SDimitry Andric uint64_t TypeOffset = 0;
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric // For v5 split or skeleton compile units only.
71bdd1243dSDimitry Andric std::optional<uint64_t> DWOId;
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric // Unit type as parsed, or derived from the section kind.
740b57cec5SDimitry Andric uint8_t UnitType = 0;
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric // Size as parsed. uint8_t for compactness.
770b57cec5SDimitry Andric uint8_t Size = 0;
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric public:
800b57cec5SDimitry Andric /// Parse a unit header from \p debug_info starting at \p offset_ptr.
815ffd83dbSDimitry Andric /// Note that \p SectionKind is used as a hint to guess the unit type
825ffd83dbSDimitry Andric /// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
835ffd83dbSDimitry Andric /// explicitly defined in the header and the hint is ignored.
845f757f3fSDimitry Andric Error extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
855ffd83dbSDimitry Andric uint64_t *offset_ptr, DWARFSectionKind SectionKind);
865ffd83dbSDimitry Andric // For units in DWARF Package File, remember the index entry and update
875ffd83dbSDimitry Andric // the abbreviation offset read by extract().
88*0fca6ea1SDimitry Andric Error applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
getOffset()898bcb0991SDimitry Andric uint64_t getOffset() const { return Offset; }
getFormParams()900b57cec5SDimitry Andric const dwarf::FormParams &getFormParams() const { return FormParams; }
getVersion()910b57cec5SDimitry Andric uint16_t getVersion() const { return FormParams.Version; }
getFormat()920b57cec5SDimitry Andric dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
getAddressByteSize()930b57cec5SDimitry Andric uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
getRefAddrByteSize()940b57cec5SDimitry Andric uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
getDwarfOffsetByteSize()950b57cec5SDimitry Andric uint8_t getDwarfOffsetByteSize() const {
960b57cec5SDimitry Andric return FormParams.getDwarfOffsetByteSize();
970b57cec5SDimitry Andric }
getLength()980b57cec5SDimitry Andric uint64_t getLength() const { return Length; }
getAbbrOffset()990b57cec5SDimitry Andric uint64_t getAbbrOffset() const { return AbbrOffset; }
getDWOId()100bdd1243dSDimitry Andric std::optional<uint64_t> getDWOId() const { return DWOId; }
setDWOId(uint64_t Id)1010b57cec5SDimitry Andric void setDWOId(uint64_t Id) {
1020b57cec5SDimitry Andric assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
1030b57cec5SDimitry Andric DWOId = Id;
1040b57cec5SDimitry Andric }
getIndexEntry()1050b57cec5SDimitry Andric const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
getTypeHash()1060b57cec5SDimitry Andric uint64_t getTypeHash() const { return TypeHash; }
getTypeOffset()1078bcb0991SDimitry Andric uint64_t getTypeOffset() const { return TypeOffset; }
getUnitType()1080b57cec5SDimitry Andric uint8_t getUnitType() const { return UnitType; }
isTypeUnit()1090b57cec5SDimitry Andric bool isTypeUnit() const {
1100b57cec5SDimitry Andric return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
1110b57cec5SDimitry Andric }
getSize()1120b57cec5SDimitry Andric uint8_t getSize() const { return Size; }
getUnitLengthFieldByteSize()1138bcb0991SDimitry Andric uint8_t getUnitLengthFieldByteSize() const {
1148bcb0991SDimitry Andric return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
1158bcb0991SDimitry Andric }
getNextUnitOffset()1168bcb0991SDimitry Andric uint64_t getNextUnitOffset() const {
1178bcb0991SDimitry Andric return Offset + Length + getUnitLengthFieldByteSize();
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric };
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
1220b57cec5SDimitry Andric DWARFSectionKind Kind);
1230b57cec5SDimitry Andric
124e8d8bef9SDimitry Andric bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
125e8d8bef9SDimitry Andric
1260b57cec5SDimitry Andric /// Describe a collection of units. Intended to hold all units either from
1270b57cec5SDimitry Andric /// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
1280b57cec5SDimitry Andric class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
1298bcb0991SDimitry Andric std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
1300b57cec5SDimitry Andric const DWARFSection *,
1310b57cec5SDimitry Andric const DWARFUnitIndex::Entry *)>
1320b57cec5SDimitry Andric Parser;
1330b57cec5SDimitry Andric int NumInfoUnits = -1;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric public:
1360b57cec5SDimitry Andric using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>;
1370b57cec5SDimitry Andric using iterator = typename UnitVector::iterator;
1380b57cec5SDimitry Andric using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
1390b57cec5SDimitry Andric
140e8d8bef9SDimitry Andric using compile_unit_range =
141e8d8bef9SDimitry Andric decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
142e8d8bef9SDimitry Andric
1438bcb0991SDimitry Andric DWARFUnit *getUnitForOffset(uint64_t Offset) const;
1440b57cec5SDimitry Andric DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric /// Read units from a .debug_info or .debug_types section. Calls made
1470b57cec5SDimitry Andric /// before finishedInfoUnits() are assumed to be for .debug_info sections,
1480b57cec5SDimitry Andric /// calls after finishedInfoUnits() are for .debug_types sections. Caller
1490b57cec5SDimitry Andric /// must not mix calls to addUnitsForSection and addUnitsForDWOSection.
1500b57cec5SDimitry Andric void addUnitsForSection(DWARFContext &C, const DWARFSection &Section,
1510b57cec5SDimitry Andric DWARFSectionKind SectionKind);
1520b57cec5SDimitry Andric /// Read units from a .debug_info.dwo or .debug_types.dwo section. Calls
1530b57cec5SDimitry Andric /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo
1540b57cec5SDimitry Andric /// sections, calls after finishedInfoUnits() are for .debug_types.dwo
1550b57cec5SDimitry Andric /// sections. Caller must not mix calls to addUnitsForSection and
1560b57cec5SDimitry Andric /// addUnitsForDWOSection.
1570b57cec5SDimitry Andric void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection,
1580b57cec5SDimitry Andric DWARFSectionKind SectionKind, bool Lazy = false);
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric /// Add an existing DWARFUnit to this UnitVector. This is used by the DWARF
1610b57cec5SDimitry Andric /// verifier to process unit separately.
1620b57cec5SDimitry Andric DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric /// Returns number of all units held by this instance.
getNumUnits()1650b57cec5SDimitry Andric unsigned getNumUnits() const { return size(); }
1660b57cec5SDimitry Andric /// Returns number of units from all .debug_info[.dwo] sections.
getNumInfoUnits()1670b57cec5SDimitry Andric unsigned getNumInfoUnits() const {
1680b57cec5SDimitry Andric return NumInfoUnits == -1 ? size() : NumInfoUnits;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric /// Returns number of units from all .debug_types[.dwo] sections.
getNumTypesUnits()1710b57cec5SDimitry Andric unsigned getNumTypesUnits() const { return size() - NumInfoUnits; }
1720b57cec5SDimitry Andric /// Indicate that parsing .debug_info[.dwo] is done, and remaining units
1730b57cec5SDimitry Andric /// will be from .debug_types[.dwo].
finishedInfoUnits()1740b57cec5SDimitry Andric void finishedInfoUnits() { NumInfoUnits = size(); }
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric private:
1770b57cec5SDimitry Andric void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj,
1780b57cec5SDimitry Andric const DWARFSection &Section, const DWARFDebugAbbrev *DA,
1790b57cec5SDimitry Andric const DWARFSection *RS, const DWARFSection *LocSection,
1800b57cec5SDimitry Andric StringRef SS, const DWARFSection &SOS,
1810b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE,
1820b57cec5SDimitry Andric bool IsDWO, bool Lazy, DWARFSectionKind SectionKind);
1830b57cec5SDimitry Andric };
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric /// Represents base address of the CU.
1860b57cec5SDimitry Andric /// Represents a unit's contribution to the string offsets table.
1870b57cec5SDimitry Andric struct StrOffsetsContributionDescriptor {
1880b57cec5SDimitry Andric uint64_t Base = 0;
1890b57cec5SDimitry Andric /// The contribution size not including the header.
1900b57cec5SDimitry Andric uint64_t Size = 0;
1910b57cec5SDimitry Andric /// Format and version.
1920b57cec5SDimitry Andric dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
1930b57cec5SDimitry Andric
StrOffsetsContributionDescriptorStrOffsetsContributionDescriptor1940b57cec5SDimitry Andric StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
1950b57cec5SDimitry Andric uint8_t Version, dwarf::DwarfFormat Format)
1960b57cec5SDimitry Andric : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
1970b57cec5SDimitry Andric StrOffsetsContributionDescriptor() = default;
1980b57cec5SDimitry Andric
getVersionStrOffsetsContributionDescriptor1990b57cec5SDimitry Andric uint8_t getVersion() const { return FormParams.Version; }
getFormatStrOffsetsContributionDescriptor2000b57cec5SDimitry Andric dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
getDwarfOffsetByteSizeStrOffsetsContributionDescriptor2010b57cec5SDimitry Andric uint8_t getDwarfOffsetByteSize() const {
2020b57cec5SDimitry Andric return FormParams.getDwarfOffsetByteSize();
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric /// Determine whether a contribution to the string offsets table is
2050b57cec5SDimitry Andric /// consistent with the relevant section size and that its length is
2060b57cec5SDimitry Andric /// a multiple of the size of one of its entries.
2070b57cec5SDimitry Andric Expected<StrOffsetsContributionDescriptor>
2080b57cec5SDimitry Andric validateContributionSize(DWARFDataExtractor &DA);
2090b57cec5SDimitry Andric };
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric class DWARFUnit {
2120b57cec5SDimitry Andric DWARFContext &Context;
2130b57cec5SDimitry Andric /// Section containing this DWARFUnit.
2140b57cec5SDimitry Andric const DWARFSection &InfoSection;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric DWARFUnitHeader Header;
2170b57cec5SDimitry Andric const DWARFDebugAbbrev *Abbrev;
2180b57cec5SDimitry Andric const DWARFSection *RangeSection;
2198bcb0991SDimitry Andric uint64_t RangeSectionBase;
220480093f4SDimitry Andric uint64_t LocSectionBase;
221480093f4SDimitry Andric
222480093f4SDimitry Andric /// Location table of this unit.
223480093f4SDimitry Andric std::unique_ptr<DWARFLocationTable> LocTable;
224480093f4SDimitry Andric
2250b57cec5SDimitry Andric const DWARFSection &LineSection;
2260b57cec5SDimitry Andric StringRef StringSection;
2270b57cec5SDimitry Andric const DWARFSection &StringOffsetSection;
2280b57cec5SDimitry Andric const DWARFSection *AddrOffsetSection;
229fe6060f1SDimitry Andric DWARFUnit *SU;
230bdd1243dSDimitry Andric std::optional<uint64_t> AddrOffsetSectionBase;
231bdd1243dSDimitry Andric bool IsLittleEndian;
2320b57cec5SDimitry Andric bool IsDWO;
2330b57cec5SDimitry Andric const DWARFUnitVector &UnitVector;
2340b57cec5SDimitry Andric
2350b57cec5SDimitry Andric /// Start, length, and DWARF format of the unit's contribution to the string
2360b57cec5SDimitry Andric /// offsets table (DWARF v5).
237bdd1243dSDimitry Andric std::optional<StrOffsetsContributionDescriptor>
238bdd1243dSDimitry Andric StringOffsetsTableContribution;
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
241bdd1243dSDimitry Andric std::optional<object::SectionedAddress> BaseAddr;
2420b57cec5SDimitry Andric /// The compile unit debug information entry items.
2430b57cec5SDimitry Andric std::vector<DWARFDebugInfoEntry> DieArray;
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric /// Map from range's start address to end address and corresponding DIE.
2460b57cec5SDimitry Andric /// IntervalMap does not support range removal, as a result, we use the
2470b57cec5SDimitry Andric /// std::map::upper_bound for address range lookup.
2480b57cec5SDimitry Andric std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
2490b57cec5SDimitry Andric
25081ad6265SDimitry Andric /// Map from the location (interpreted DW_AT_location) of a DW_TAG_variable,
25181ad6265SDimitry Andric /// to the end address and the corresponding DIE.
25281ad6265SDimitry Andric std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap;
25381ad6265SDimitry Andric DenseSet<uint64_t> RootsParsedForVariables;
25481ad6265SDimitry Andric
2550b57cec5SDimitry Andric using die_iterator_range =
2560b57cec5SDimitry Andric iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric std::shared_ptr<DWARFUnit> DWO;
2590b57cec5SDimitry Andric
260bdd1243dSDimitry Andric protected:
2611db9f3b2SDimitry Andric friend dwarf_linker::parallel::CompileUnit;
26206c3fb27SDimitry Andric
263bdd1243dSDimitry Andric /// Return the index of a \p Die entry inside the unit's DIE vector.
264bdd1243dSDimitry Andric ///
265bdd1243dSDimitry Andric /// It is illegal to call this method with a DIE that hasn't be
266bdd1243dSDimitry Andric /// created by this unit. In other word, it's illegal to call this
267bdd1243dSDimitry Andric /// method on a DIE that isn't accessible by following
268bdd1243dSDimitry Andric /// children/sibling links starting from this unit's getUnitDIE().
getDIEIndex(const DWARFDebugInfoEntry * Die)269bdd1243dSDimitry Andric uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
2700b57cec5SDimitry Andric auto First = DieArray.data();
2710b57cec5SDimitry Andric assert(Die >= First && Die < First + DieArray.size());
2720b57cec5SDimitry Andric return Die - First;
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric
275bdd1243dSDimitry Andric /// Return DWARFDebugInfoEntry for the specified index \p Index.
getDebugInfoEntry(unsigned Index)276bdd1243dSDimitry Andric const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
277bdd1243dSDimitry Andric assert(Index < DieArray.size());
278bdd1243dSDimitry Andric return &DieArray[Index];
279bdd1243dSDimitry Andric }
280bdd1243dSDimitry Andric
281bdd1243dSDimitry Andric const DWARFDebugInfoEntry *
282bdd1243dSDimitry Andric getParentEntry(const DWARFDebugInfoEntry *Die) const;
283bdd1243dSDimitry Andric const DWARFDebugInfoEntry *
284bdd1243dSDimitry Andric getSiblingEntry(const DWARFDebugInfoEntry *Die) const;
285bdd1243dSDimitry Andric const DWARFDebugInfoEntry *
286bdd1243dSDimitry Andric getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const;
287bdd1243dSDimitry Andric const DWARFDebugInfoEntry *
288bdd1243dSDimitry Andric getFirstChildEntry(const DWARFDebugInfoEntry *Die) const;
289bdd1243dSDimitry Andric const DWARFDebugInfoEntry *
290bdd1243dSDimitry Andric getLastChildEntry(const DWARFDebugInfoEntry *Die) const;
291bdd1243dSDimitry Andric
getHeader()2920b57cec5SDimitry Andric const DWARFUnitHeader &getHeader() const { return Header; }
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric /// Find the unit's contribution to the string offsets table and determine its
2950b57cec5SDimitry Andric /// length and form. The given offset is expected to be derived from the unit
2960b57cec5SDimitry Andric /// DIE's DW_AT_str_offsets_base attribute.
297bdd1243dSDimitry Andric Expected<std::optional<StrOffsetsContributionDescriptor>>
2980b57cec5SDimitry Andric determineStringOffsetsTableContribution(DWARFDataExtractor &DA);
2990b57cec5SDimitry Andric
3000b57cec5SDimitry Andric /// Find the unit's contribution to the string offsets table and determine its
3010b57cec5SDimitry Andric /// length and form. The given offset is expected to be 0 in a dwo file or,
3020b57cec5SDimitry Andric /// in a dwp file, the start of the unit's contribution to the string offsets
3030b57cec5SDimitry Andric /// table section (as determined by the index table).
304bdd1243dSDimitry Andric Expected<std::optional<StrOffsetsContributionDescriptor>>
3050b57cec5SDimitry Andric determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA);
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric public:
3080b57cec5SDimitry Andric DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
3090b57cec5SDimitry Andric const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
3100b57cec5SDimitry Andric const DWARFSection *RS, const DWARFSection *LocSection,
3110b57cec5SDimitry Andric StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
3120b57cec5SDimitry Andric const DWARFSection &LS, bool LE, bool IsDWO,
3130b57cec5SDimitry Andric const DWARFUnitVector &UnitVector);
3140b57cec5SDimitry Andric
3150b57cec5SDimitry Andric virtual ~DWARFUnit();
3160b57cec5SDimitry Andric
isLittleEndian()317bdd1243dSDimitry Andric bool isLittleEndian() const { return IsLittleEndian; }
isDWOUnit()3180b57cec5SDimitry Andric bool isDWOUnit() const { return IsDWO; }
getContext()3190b57cec5SDimitry Andric DWARFContext& getContext() const { return Context; }
getInfoSection()3200b57cec5SDimitry Andric const DWARFSection &getInfoSection() const { return InfoSection; }
getOffset()3218bcb0991SDimitry Andric uint64_t getOffset() const { return Header.getOffset(); }
getFormParams()3220b57cec5SDimitry Andric const dwarf::FormParams &getFormParams() const {
3230b57cec5SDimitry Andric return Header.getFormParams();
3240b57cec5SDimitry Andric }
getVersion()3250b57cec5SDimitry Andric uint16_t getVersion() const { return Header.getVersion(); }
getAddressByteSize()3260b57cec5SDimitry Andric uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
getRefAddrByteSize()3270b57cec5SDimitry Andric uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
getDwarfOffsetByteSize()3280b57cec5SDimitry Andric uint8_t getDwarfOffsetByteSize() const {
3290b57cec5SDimitry Andric return Header.getDwarfOffsetByteSize();
3300b57cec5SDimitry Andric }
331fe6060f1SDimitry Andric /// Size in bytes of the parsed unit header.
getHeaderSize()332fe6060f1SDimitry Andric uint32_t getHeaderSize() const { return Header.getSize(); }
getLength()3338bcb0991SDimitry Andric uint64_t getLength() const { return Header.getLength(); }
getFormat()3345ffd83dbSDimitry Andric dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
getUnitType()3350b57cec5SDimitry Andric uint8_t getUnitType() const { return Header.getUnitType(); }
isTypeUnit()3360b57cec5SDimitry Andric bool isTypeUnit() const { return Header.isTypeUnit(); }
getAbbrOffset()337e8d8bef9SDimitry Andric uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); }
getNextUnitOffset()3388bcb0991SDimitry Andric uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
getLineSection()3390b57cec5SDimitry Andric const DWARFSection &getLineSection() const { return LineSection; }
getStringSection()3400b57cec5SDimitry Andric StringRef getStringSection() const { return StringSection; }
getStringOffsetSection()3410b57cec5SDimitry Andric const DWARFSection &getStringOffsetSection() const {
3420b57cec5SDimitry Andric return StringOffsetSection;
3430b57cec5SDimitry Andric }
3440b57cec5SDimitry Andric
setSkeletonUnit(DWARFUnit * SU)345fe6060f1SDimitry Andric void setSkeletonUnit(DWARFUnit *SU) { this->SU = SU; }
346fe6060f1SDimitry Andric // Returns itself if not using Split DWARF, or if the unit is a skeleton unit
347fe6060f1SDimitry Andric // - otherwise returns the split full unit's corresponding skeleton, if
348fe6060f1SDimitry Andric // available.
getLinkedUnit()349fe6060f1SDimitry Andric DWARFUnit *getLinkedUnit() { return IsDWO ? SU : this; }
350fe6060f1SDimitry Andric
setAddrOffsetSection(const DWARFSection * AOS,uint64_t Base)3515ffd83dbSDimitry Andric void setAddrOffsetSection(const DWARFSection *AOS, uint64_t Base) {
3520b57cec5SDimitry Andric AddrOffsetSection = AOS;
3530b57cec5SDimitry Andric AddrOffsetSectionBase = Base;
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
getAddrOffsetSectionBase()356bdd1243dSDimitry Andric std::optional<uint64_t> getAddrOffsetSectionBase() const {
357fe6060f1SDimitry Andric return AddrOffsetSectionBase;
358fe6060f1SDimitry Andric }
359fe6060f1SDimitry Andric
36006c3fb27SDimitry Andric /// Returns offset to the indexed address value inside .debug_addr section.
getIndexedAddressOffset(uint64_t Index)36106c3fb27SDimitry Andric std::optional<uint64_t> getIndexedAddressOffset(uint64_t Index) {
36206c3fb27SDimitry Andric if (std::optional<uint64_t> AddrOffsetSectionBase =
36306c3fb27SDimitry Andric getAddrOffsetSectionBase())
36406c3fb27SDimitry Andric return *AddrOffsetSectionBase + Index * getAddressByteSize();
36506c3fb27SDimitry Andric
36606c3fb27SDimitry Andric return std::nullopt;
36706c3fb27SDimitry Andric }
36806c3fb27SDimitry Andric
3690b57cec5SDimitry Andric /// Recursively update address to Die map.
3700b57cec5SDimitry Andric void updateAddressDieMap(DWARFDie Die);
3710b57cec5SDimitry Andric
37281ad6265SDimitry Andric /// Recursively update address to variable Die map.
37381ad6265SDimitry Andric void updateVariableDieMap(DWARFDie Die);
37481ad6265SDimitry Andric
setRangesSection(const DWARFSection * RS,uint64_t Base)3758bcb0991SDimitry Andric void setRangesSection(const DWARFSection *RS, uint64_t Base) {
3760b57cec5SDimitry Andric RangeSection = RS;
3770b57cec5SDimitry Andric RangeSectionBase = Base;
3780b57cec5SDimitry Andric }
379480093f4SDimitry Andric
getLocSectionBase()380480093f4SDimitry Andric uint64_t getLocSectionBase() const {
381480093f4SDimitry Andric return LocSectionBase;
382480093f4SDimitry Andric }
3830b57cec5SDimitry Andric
384bdd1243dSDimitry Andric std::optional<object::SectionedAddress>
3850b57cec5SDimitry Andric getAddrOffsetSectionItem(uint32_t Index) const;
3860eae32dcSDimitry Andric Expected<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
3870b57cec5SDimitry Andric
3880b57cec5SDimitry Andric DWARFDataExtractor getDebugInfoExtractor() const;
3890b57cec5SDimitry Andric
getStringExtractor()3900b57cec5SDimitry Andric DataExtractor getStringExtractor() const {
3910b57cec5SDimitry Andric return DataExtractor(StringSection, false, 0);
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric
getLocationTable()394480093f4SDimitry Andric const DWARFLocationTable &getLocationTable() { return *LocTable; }
395480093f4SDimitry Andric
3960b57cec5SDimitry Andric /// Extract the range list referenced by this compile unit from the
3970b57cec5SDimitry Andric /// .debug_ranges section. If the extraction is unsuccessful, an error
3980b57cec5SDimitry Andric /// is returned. Successful extraction requires that the compile unit
3990b57cec5SDimitry Andric /// has already been extracted.
4008bcb0991SDimitry Andric Error extractRangeList(uint64_t RangeListOffset,
4010b57cec5SDimitry Andric DWARFDebugRangeList &RangeList) const;
4020b57cec5SDimitry Andric void clear();
4030b57cec5SDimitry Andric
404bdd1243dSDimitry Andric const std::optional<StrOffsetsContributionDescriptor> &
getStringOffsetsTableContribution()4055f757f3fSDimitry Andric getStringOffsetsTableContribution() {
4065f757f3fSDimitry Andric extractDIEsIfNeeded(true /*CUDIeOnly*/);
4070b57cec5SDimitry Andric return StringOffsetsTableContribution;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric
getDwarfStringOffsetsByteSize()4100b57cec5SDimitry Andric uint8_t getDwarfStringOffsetsByteSize() const {
4110b57cec5SDimitry Andric assert(StringOffsetsTableContribution);
4120b57cec5SDimitry Andric return StringOffsetsTableContribution->getDwarfOffsetByteSize();
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
getStringOffsetsBase()4150b57cec5SDimitry Andric uint64_t getStringOffsetsBase() const {
4160b57cec5SDimitry Andric assert(StringOffsetsTableContribution);
4170b57cec5SDimitry Andric return StringOffsetsTableContribution->Base;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric
getAbbreviationsOffset()420fe6060f1SDimitry Andric uint64_t getAbbreviationsOffset() const { return Header.getAbbrOffset(); }
421fe6060f1SDimitry Andric
4220b57cec5SDimitry Andric const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
4230b57cec5SDimitry Andric
isMatchingUnitTypeAndTag(uint8_t UnitType,dwarf::Tag Tag)4240b57cec5SDimitry Andric static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
4250b57cec5SDimitry Andric switch (UnitType) {
4260b57cec5SDimitry Andric case dwarf::DW_UT_compile:
4270b57cec5SDimitry Andric return Tag == dwarf::DW_TAG_compile_unit;
4280b57cec5SDimitry Andric case dwarf::DW_UT_type:
4290b57cec5SDimitry Andric return Tag == dwarf::DW_TAG_type_unit;
4300b57cec5SDimitry Andric case dwarf::DW_UT_partial:
4310b57cec5SDimitry Andric return Tag == dwarf::DW_TAG_partial_unit;
4320b57cec5SDimitry Andric case dwarf::DW_UT_skeleton:
4330b57cec5SDimitry Andric return Tag == dwarf::DW_TAG_skeleton_unit;
4340b57cec5SDimitry Andric case dwarf::DW_UT_split_compile:
4350b57cec5SDimitry Andric case dwarf::DW_UT_split_type:
4360b57cec5SDimitry Andric return dwarf::isUnitType(Tag);
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric return false;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric
441bdd1243dSDimitry Andric std::optional<object::SectionedAddress> getBaseAddress();
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
4440b57cec5SDimitry Andric extractDIEsIfNeeded(ExtractUnitDIEOnly);
4450b57cec5SDimitry Andric if (DieArray.empty())
4460b57cec5SDimitry Andric return DWARFDie();
4470b57cec5SDimitry Andric return DWARFDie(this, &DieArray[0]);
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric
450bdd1243dSDimitry Andric DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true,
451bdd1243dSDimitry Andric StringRef DWOAlternativeLocation = {}) {
452bdd1243dSDimitry Andric parseDWO(DWOAlternativeLocation);
453bdd1243dSDimitry Andric return DWO ? DWO->getUnitDIE(ExtractUnitDIEOnly)
454bdd1243dSDimitry Andric : getUnitDIE(ExtractUnitDIEOnly);
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric const char *getCompilationDir();
getDWOId()458bdd1243dSDimitry Andric std::optional<uint64_t> getDWOId() {
4590b57cec5SDimitry Andric extractDIEsIfNeeded(/*CUDieOnly*/ true);
4600b57cec5SDimitry Andric return getHeader().getDWOId();
4610b57cec5SDimitry Andric }
setDWOId(uint64_t NewID)4620b57cec5SDimitry Andric void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
4630b57cec5SDimitry Andric
4640b57cec5SDimitry Andric /// Return a vector of address ranges resulting from a (possibly encoded)
4650b57cec5SDimitry Andric /// range list starting at a given offset in the appropriate ranges section.
4668bcb0991SDimitry Andric Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset);
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric /// Return a vector of address ranges retrieved from an encoded range
4690b57cec5SDimitry Andric /// list whose offset is found via a table lookup given an index (DWARF v5
4700b57cec5SDimitry Andric /// and later).
4710b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
4720b57cec5SDimitry Andric
4730b57cec5SDimitry Andric /// Return a rangelist's offset based on an index. The index designates
4740b57cec5SDimitry Andric /// an entry in the rangelist table's offset array and is supplied by
4750b57cec5SDimitry Andric /// DW_FORM_rnglistx.
476bdd1243dSDimitry Andric std::optional<uint64_t> getRnglistOffset(uint32_t Index);
4770b57cec5SDimitry Andric
478bdd1243dSDimitry Andric std::optional<uint64_t> getLoclistOffset(uint32_t Index);
479e8d8bef9SDimitry Andric
4800b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> collectAddressRanges();
4810b57cec5SDimitry Andric
482480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector>
483480093f4SDimitry Andric findLoclistFromOffset(uint64_t Offset);
484480093f4SDimitry Andric
4850b57cec5SDimitry Andric /// Returns subprogram DIE with address range encompassing the provided
4860b57cec5SDimitry Andric /// address. The pointer is alive as long as parsed compile unit DIEs are not
4870b57cec5SDimitry Andric /// cleared.
4880b57cec5SDimitry Andric DWARFDie getSubroutineForAddress(uint64_t Address);
4890b57cec5SDimitry Andric
49081ad6265SDimitry Andric /// Returns variable DIE for the address provided. The pointer is alive as
49181ad6265SDimitry Andric /// long as parsed compile unit DIEs are not cleared.
49281ad6265SDimitry Andric DWARFDie getVariableForAddress(uint64_t Address);
49381ad6265SDimitry Andric
4940b57cec5SDimitry Andric /// getInlinedChainForAddress - fetches inlined chain for a given address.
4950b57cec5SDimitry Andric /// Returns empty chain if there is no subprogram containing address. The
4960b57cec5SDimitry Andric /// chain is valid as long as parsed compile unit DIEs are not cleared.
4970b57cec5SDimitry Andric void getInlinedChainForAddress(uint64_t Address,
4980b57cec5SDimitry Andric SmallVectorImpl<DWARFDie> &InlinedChain);
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric /// Return the DWARFUnitVector containing this unit.
getUnitVector()5010b57cec5SDimitry Andric const DWARFUnitVector &getUnitVector() const { return UnitVector; }
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric /// Returns the number of DIEs in the unit. Parses the unit
5040b57cec5SDimitry Andric /// if necessary.
getNumDIEs()5050b57cec5SDimitry Andric unsigned getNumDIEs() {
5060b57cec5SDimitry Andric extractDIEsIfNeeded(false);
5070b57cec5SDimitry Andric return DieArray.size();
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric
5100b57cec5SDimitry Andric /// Return the index of a DIE inside the unit's DIE vector.
5110b57cec5SDimitry Andric ///
5120b57cec5SDimitry Andric /// It is illegal to call this method with a DIE that hasn't be
5130b57cec5SDimitry Andric /// created by this unit. In other word, it's illegal to call this
5140b57cec5SDimitry Andric /// method on a DIE that isn't accessible by following
5150b57cec5SDimitry Andric /// children/sibling links starting from this unit's getUnitDIE().
getDIEIndex(const DWARFDie & D)516bdd1243dSDimitry Andric uint32_t getDIEIndex(const DWARFDie &D) const {
5170b57cec5SDimitry Andric return getDIEIndex(D.getDebugInfoEntry());
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric
520bdd1243dSDimitry Andric /// Return the DIE object at the given index \p Index.
getDIEAtIndex(unsigned Index)5210b57cec5SDimitry Andric DWARFDie getDIEAtIndex(unsigned Index) {
522bdd1243dSDimitry Andric return DWARFDie(this, getDebugInfoEntry(Index));
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric DWARFDie getParent(const DWARFDebugInfoEntry *Die);
5260b57cec5SDimitry Andric DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
5270b57cec5SDimitry Andric DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
5280b57cec5SDimitry Andric DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
5290b57cec5SDimitry Andric DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
5300b57cec5SDimitry Andric
531bdd1243dSDimitry Andric /// Return the DIE object for a given offset \p Offset inside the
5320b57cec5SDimitry Andric /// unit's DIE vector.
getDIEForOffset(uint64_t Offset)5338bcb0991SDimitry Andric DWARFDie getDIEForOffset(uint64_t Offset) {
534bdd1243dSDimitry Andric if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset))
535bdd1243dSDimitry Andric return DWARFDie(this, &DieArray[*DieIdx]);
536bdd1243dSDimitry Andric
537bdd1243dSDimitry Andric return DWARFDie();
538bdd1243dSDimitry Andric }
539bdd1243dSDimitry Andric
540bdd1243dSDimitry Andric /// Return the DIE index for a given offset \p Offset inside the
541bdd1243dSDimitry Andric /// unit's DIE vector.
getDIEIndexForOffset(uint64_t Offset)542bdd1243dSDimitry Andric std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
5430b57cec5SDimitry Andric extractDIEsIfNeeded(false);
5440b57cec5SDimitry Andric auto It =
5450b57cec5SDimitry Andric llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
5460b57cec5SDimitry Andric return DIE.getOffset() < Offset;
5470b57cec5SDimitry Andric });
5480b57cec5SDimitry Andric if (It != DieArray.end() && It->getOffset() == Offset)
549bdd1243dSDimitry Andric return It - DieArray.begin();
550bdd1243dSDimitry Andric return std::nullopt;
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric
getLineTableOffset()5530b57cec5SDimitry Andric uint32_t getLineTableOffset() const {
5540b57cec5SDimitry Andric if (auto IndexEntry = Header.getIndexEntry())
5555ffd83dbSDimitry Andric if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LINE))
556bdd1243dSDimitry Andric return Contrib->getOffset32();
5570b57cec5SDimitry Andric return 0;
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric
dies()5600b57cec5SDimitry Andric die_iterator_range dies() {
5610b57cec5SDimitry Andric extractDIEsIfNeeded(false);
5620b57cec5SDimitry Andric return die_iterator_range(DieArray.begin(), DieArray.end());
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andric virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
5668bcb0991SDimitry Andric
5678bcb0991SDimitry Andric Error tryExtractDIEsIfNeeded(bool CUDieOnly);
5688bcb0991SDimitry Andric
5690b57cec5SDimitry Andric private:
5700b57cec5SDimitry Andric /// Size in bytes of the .debug_info data associated with this compile unit.
getDebugInfoSize()5710b57cec5SDimitry Andric size_t getDebugInfoSize() const {
5728bcb0991SDimitry Andric return Header.getLength() + Header.getUnitLengthFieldByteSize() -
5738bcb0991SDimitry Andric getHeaderSize();
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
5778bcb0991SDimitry Andric /// hasn't already been done
5788bcb0991SDimitry Andric void extractDIEsIfNeeded(bool CUDieOnly);
5790b57cec5SDimitry Andric
5800b57cec5SDimitry Andric /// extractDIEsToVector - Appends all parsed DIEs to a vector.
5810b57cec5SDimitry Andric void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
5820b57cec5SDimitry Andric std::vector<DWARFDebugInfoEntry> &DIEs) const;
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric /// clearDIEs - Clear parsed DIEs to keep memory usage low.
5850b57cec5SDimitry Andric void clearDIEs(bool KeepCUDie);
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric /// parseDWO - Parses .dwo file for current compile unit. Returns true if
5880b57cec5SDimitry Andric /// it was actually constructed.
589bdd1243dSDimitry Andric /// The \p AlternativeLocation specifies an alternative location to get
590bdd1243dSDimitry Andric /// the DWARF context for the DWO object; this is the case when it has
591bdd1243dSDimitry Andric /// been moved from its original location.
592bdd1243dSDimitry Andric bool parseDWO(StringRef AlternativeLocation = {});
5930b57cec5SDimitry Andric };
5940b57cec5SDimitry Andric
isCompileUnit(const std::unique_ptr<DWARFUnit> & U)595e8d8bef9SDimitry Andric inline bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U) {
596e8d8bef9SDimitry Andric return !U->isTypeUnit();
597e8d8bef9SDimitry Andric }
598e8d8bef9SDimitry Andric
5990b57cec5SDimitry Andric } // end namespace llvm
6000b57cec5SDimitry Andric
6010b57cec5SDimitry Andric #endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
602