File indexing completed on 2026-05-10 08:43:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
0011
0012 #include "llvm/ADT/DenseSet.h"
0013 #include "llvm/ADT/STLExtras.h"
0014 #include "llvm/ADT/SmallVector.h"
0015 #include "llvm/ADT/StringRef.h"
0016 #include "llvm/ADT/iterator_range.h"
0017 #include "llvm/BinaryFormat/Dwarf.h"
0018 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
0019 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
0020 #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
0021 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
0022 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
0023 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
0024 #include "llvm/Support/DataExtractor.h"
0025 #include <cassert>
0026 #include <cstddef>
0027 #include <cstdint>
0028 #include <map>
0029 #include <memory>
0030 #include <set>
0031 #include <utility>
0032 #include <vector>
0033
0034 namespace llvm {
0035
0036 class DWARFAbbreviationDeclarationSet;
0037 class DWARFContext;
0038 class DWARFDebugAbbrev;
0039 class DWARFUnit;
0040 class DWARFDebugRangeList;
0041 class DWARFLocationTable;
0042 class DWARFObject;
0043 class raw_ostream;
0044 struct DIDumpOptions;
0045 struct DWARFSection;
0046 namespace dwarf_linker {
0047 namespace parallel {
0048 class CompileUnit;
0049 }
0050 }
0051
0052
0053
0054
0055 class DWARFUnitHeader {
0056
0057 uint64_t Offset = 0;
0058
0059 dwarf::FormParams FormParams;
0060 uint64_t Length = 0;
0061 uint64_t AbbrOffset = 0;
0062
0063
0064 const DWARFUnitIndex::Entry *IndexEntry = nullptr;
0065
0066
0067 uint64_t TypeHash = 0;
0068 uint64_t TypeOffset = 0;
0069
0070
0071 std::optional<uint64_t> DWOId;
0072
0073
0074 uint8_t UnitType = 0;
0075
0076
0077 uint8_t Size = 0;
0078
0079 public:
0080
0081
0082
0083
0084 Error extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
0085 uint64_t *offset_ptr, DWARFSectionKind SectionKind);
0086
0087
0088 Error applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
0089 uint64_t getOffset() const { return Offset; }
0090 const dwarf::FormParams &getFormParams() const { return FormParams; }
0091 uint16_t getVersion() const { return FormParams.Version; }
0092 dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
0093 uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
0094 uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
0095 uint8_t getDwarfOffsetByteSize() const {
0096 return FormParams.getDwarfOffsetByteSize();
0097 }
0098 uint64_t getLength() const { return Length; }
0099 uint64_t getAbbrOffset() const { return AbbrOffset; }
0100 std::optional<uint64_t> getDWOId() const { return DWOId; }
0101 void setDWOId(uint64_t Id) {
0102 assert((!DWOId || *DWOId == Id) && "setting DWOId to a different value");
0103 DWOId = Id;
0104 }
0105 const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
0106 uint64_t getTypeHash() const { return TypeHash; }
0107 uint64_t getTypeOffset() const { return TypeOffset; }
0108 uint8_t getUnitType() const { return UnitType; }
0109 bool isTypeUnit() const {
0110 return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
0111 }
0112 uint8_t getSize() const { return Size; }
0113 uint8_t getUnitLengthFieldByteSize() const {
0114 return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
0115 }
0116 uint64_t getNextUnitOffset() const {
0117 return Offset + Length + getUnitLengthFieldByteSize();
0118 }
0119 };
0120
0121 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
0122 DWARFSectionKind Kind);
0123
0124 bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
0125
0126
0127
0128 class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
0129 std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
0130 const DWARFSection *,
0131 const DWARFUnitIndex::Entry *)>
0132 Parser;
0133 int NumInfoUnits = -1;
0134
0135 public:
0136 using UnitVector = SmallVectorImpl<std::unique_ptr<DWARFUnit>>;
0137 using iterator = typename UnitVector::iterator;
0138 using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
0139
0140 using compile_unit_range =
0141 decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
0142
0143 DWARFUnit *getUnitForOffset(uint64_t Offset) const;
0144 DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
0145
0146
0147
0148
0149
0150 void addUnitsForSection(DWARFContext &C, const DWARFSection &Section,
0151 DWARFSectionKind SectionKind);
0152
0153
0154
0155
0156
0157 void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection,
0158 DWARFSectionKind SectionKind, bool Lazy = false);
0159
0160
0161
0162 DWARFUnit *addUnit(std::unique_ptr<DWARFUnit> Unit);
0163
0164
0165 unsigned getNumUnits() const { return size(); }
0166
0167 unsigned getNumInfoUnits() const {
0168 return NumInfoUnits == -1 ? size() : NumInfoUnits;
0169 }
0170
0171 unsigned getNumTypesUnits() const { return size() - NumInfoUnits; }
0172
0173
0174 void finishedInfoUnits() { NumInfoUnits = size(); }
0175
0176 private:
0177 void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj,
0178 const DWARFSection &Section, const DWARFDebugAbbrev *DA,
0179 const DWARFSection *RS, const DWARFSection *LocSection,
0180 StringRef SS, const DWARFSection &SOS,
0181 const DWARFSection *AOS, const DWARFSection &LS, bool LE,
0182 bool IsDWO, bool Lazy, DWARFSectionKind SectionKind);
0183 };
0184
0185
0186
0187 struct StrOffsetsContributionDescriptor {
0188 uint64_t Base = 0;
0189
0190 uint64_t Size = 0;
0191
0192 dwarf::FormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32};
0193
0194 StrOffsetsContributionDescriptor(uint64_t Base, uint64_t Size,
0195 uint8_t Version, dwarf::DwarfFormat Format)
0196 : Base(Base), Size(Size), FormParams({Version, 0, Format}) {}
0197 StrOffsetsContributionDescriptor() = default;
0198
0199 uint8_t getVersion() const { return FormParams.Version; }
0200 dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
0201 uint8_t getDwarfOffsetByteSize() const {
0202 return FormParams.getDwarfOffsetByteSize();
0203 }
0204
0205
0206
0207 Expected<StrOffsetsContributionDescriptor>
0208 validateContributionSize(DWARFDataExtractor &DA);
0209 };
0210
0211 class DWARFUnit {
0212 DWARFContext &Context;
0213
0214 const DWARFSection &InfoSection;
0215
0216 DWARFUnitHeader Header;
0217 const DWARFDebugAbbrev *Abbrev;
0218 const DWARFSection *RangeSection;
0219 uint64_t RangeSectionBase;
0220 uint64_t LocSectionBase;
0221
0222
0223 std::unique_ptr<DWARFLocationTable> LocTable;
0224
0225 const DWARFSection &LineSection;
0226 StringRef StringSection;
0227 const DWARFSection &StringOffsetSection;
0228 const DWARFSection *AddrOffsetSection;
0229 DWARFUnit *SU;
0230 std::optional<uint64_t> AddrOffsetSectionBase;
0231 bool IsLittleEndian;
0232 bool IsDWO;
0233 const DWARFUnitVector &UnitVector;
0234
0235
0236
0237 std::optional<StrOffsetsContributionDescriptor>
0238 StringOffsetsTableContribution;
0239
0240 mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
0241 std::optional<object::SectionedAddress> BaseAddr;
0242
0243 std::vector<DWARFDebugInfoEntry> DieArray;
0244
0245
0246
0247
0248 std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
0249
0250
0251
0252 std::map<uint64_t, std::pair<uint64_t, DWARFDie>> VariableDieMap;
0253 DenseSet<uint64_t> RootsParsedForVariables;
0254
0255 using die_iterator_range =
0256 iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
0257
0258 std::shared_ptr<DWARFUnit> DWO;
0259
0260 protected:
0261 friend dwarf_linker::parallel::CompileUnit;
0262
0263
0264
0265
0266
0267
0268
0269 uint32_t getDIEIndex(const DWARFDebugInfoEntry *Die) const {
0270 auto First = DieArray.data();
0271 assert(Die >= First && Die < First + DieArray.size());
0272 return Die - First;
0273 }
0274
0275
0276 const DWARFDebugInfoEntry *getDebugInfoEntry(unsigned Index) const {
0277 assert(Index < DieArray.size());
0278 return &DieArray[Index];
0279 }
0280
0281 const DWARFDebugInfoEntry *
0282 getParentEntry(const DWARFDebugInfoEntry *Die) const;
0283 const DWARFDebugInfoEntry *
0284 getSiblingEntry(const DWARFDebugInfoEntry *Die) const;
0285 const DWARFDebugInfoEntry *
0286 getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const;
0287 const DWARFDebugInfoEntry *
0288 getFirstChildEntry(const DWARFDebugInfoEntry *Die) const;
0289 const DWARFDebugInfoEntry *
0290 getLastChildEntry(const DWARFDebugInfoEntry *Die) const;
0291
0292 const DWARFUnitHeader &getHeader() const { return Header; }
0293
0294
0295
0296
0297 Expected<std::optional<StrOffsetsContributionDescriptor>>
0298 determineStringOffsetsTableContribution(DWARFDataExtractor &DA);
0299
0300
0301
0302
0303
0304 Expected<std::optional<StrOffsetsContributionDescriptor>>
0305 determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA);
0306
0307 public:
0308 DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
0309 const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
0310 const DWARFSection *RS, const DWARFSection *LocSection,
0311 StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
0312 const DWARFSection &LS, bool LE, bool IsDWO,
0313 const DWARFUnitVector &UnitVector);
0314
0315 virtual ~DWARFUnit();
0316
0317 bool isLittleEndian() const { return IsLittleEndian; }
0318 bool isDWOUnit() const { return IsDWO; }
0319 DWARFContext& getContext() const { return Context; }
0320 const DWARFSection &getInfoSection() const { return InfoSection; }
0321 uint64_t getOffset() const { return Header.getOffset(); }
0322 const dwarf::FormParams &getFormParams() const {
0323 return Header.getFormParams();
0324 }
0325 uint16_t getVersion() const { return Header.getVersion(); }
0326 uint8_t getAddressByteSize() const { return Header.getAddressByteSize(); }
0327 uint8_t getRefAddrByteSize() const { return Header.getRefAddrByteSize(); }
0328 uint8_t getDwarfOffsetByteSize() const {
0329 return Header.getDwarfOffsetByteSize();
0330 }
0331
0332 uint32_t getHeaderSize() const { return Header.getSize(); }
0333 uint64_t getLength() const { return Header.getLength(); }
0334 dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
0335 uint8_t getUnitType() const { return Header.getUnitType(); }
0336 bool isTypeUnit() const { return Header.isTypeUnit(); }
0337 uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); }
0338 uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
0339 const DWARFSection &getLineSection() const { return LineSection; }
0340 StringRef getStringSection() const { return StringSection; }
0341 const DWARFSection &getStringOffsetSection() const {
0342 return StringOffsetSection;
0343 }
0344
0345 void setSkeletonUnit(DWARFUnit *SU) { this->SU = SU; }
0346
0347
0348
0349 DWARFUnit *getLinkedUnit() { return IsDWO ? SU : this; }
0350
0351 void setAddrOffsetSection(const DWARFSection *AOS, uint64_t Base) {
0352 AddrOffsetSection = AOS;
0353 AddrOffsetSectionBase = Base;
0354 }
0355
0356 std::optional<uint64_t> getAddrOffsetSectionBase() const {
0357 return AddrOffsetSectionBase;
0358 }
0359
0360
0361 std::optional<uint64_t> getIndexedAddressOffset(uint64_t Index) {
0362 if (std::optional<uint64_t> AddrOffsetSectionBase =
0363 getAddrOffsetSectionBase())
0364 return *AddrOffsetSectionBase + Index * getAddressByteSize();
0365
0366 return std::nullopt;
0367 }
0368
0369
0370 void updateAddressDieMap(DWARFDie Die);
0371
0372
0373 void updateVariableDieMap(DWARFDie Die);
0374
0375 void setRangesSection(const DWARFSection *RS, uint64_t Base) {
0376 RangeSection = RS;
0377 RangeSectionBase = Base;
0378 }
0379
0380 uint64_t getLocSectionBase() const {
0381 return LocSectionBase;
0382 }
0383
0384 std::optional<object::SectionedAddress>
0385 getAddrOffsetSectionItem(uint32_t Index) const;
0386 Expected<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
0387
0388 DWARFDataExtractor getDebugInfoExtractor() const;
0389
0390 DataExtractor getStringExtractor() const {
0391 return DataExtractor(StringSection, false, 0);
0392 }
0393
0394 const DWARFLocationTable &getLocationTable() { return *LocTable; }
0395
0396
0397
0398
0399
0400 Error extractRangeList(uint64_t RangeListOffset,
0401 DWARFDebugRangeList &RangeList) const;
0402 void clear();
0403
0404 const std::optional<StrOffsetsContributionDescriptor> &
0405 getStringOffsetsTableContribution() {
0406 extractDIEsIfNeeded(true );
0407 return StringOffsetsTableContribution;
0408 }
0409
0410 uint8_t getDwarfStringOffsetsByteSize() const {
0411 assert(StringOffsetsTableContribution);
0412 return StringOffsetsTableContribution->getDwarfOffsetByteSize();
0413 }
0414
0415 uint64_t getStringOffsetsBase() const {
0416 assert(StringOffsetsTableContribution);
0417 return StringOffsetsTableContribution->Base;
0418 }
0419
0420 uint64_t getAbbreviationsOffset() const { return Header.getAbbrOffset(); }
0421
0422 const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
0423
0424 static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
0425 switch (UnitType) {
0426 case dwarf::DW_UT_compile:
0427 return Tag == dwarf::DW_TAG_compile_unit;
0428 case dwarf::DW_UT_type:
0429 return Tag == dwarf::DW_TAG_type_unit;
0430 case dwarf::DW_UT_partial:
0431 return Tag == dwarf::DW_TAG_partial_unit;
0432 case dwarf::DW_UT_skeleton:
0433 return Tag == dwarf::DW_TAG_skeleton_unit;
0434 case dwarf::DW_UT_split_compile:
0435 case dwarf::DW_UT_split_type:
0436 return dwarf::isUnitType(Tag);
0437 }
0438 return false;
0439 }
0440
0441 std::optional<object::SectionedAddress> getBaseAddress();
0442
0443 DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
0444 extractDIEsIfNeeded(ExtractUnitDIEOnly);
0445 if (DieArray.empty())
0446 return DWARFDie();
0447 return DWARFDie(this, &DieArray[0]);
0448 }
0449
0450 DWARFDie getNonSkeletonUnitDIE(bool ExtractUnitDIEOnly = true,
0451 StringRef DWOAlternativeLocation = {}) {
0452 parseDWO(DWOAlternativeLocation);
0453 return DWO ? DWO->getUnitDIE(ExtractUnitDIEOnly)
0454 : getUnitDIE(ExtractUnitDIEOnly);
0455 }
0456
0457 const char *getCompilationDir();
0458 std::optional<uint64_t> getDWOId() {
0459 extractDIEsIfNeeded( true);
0460 return getHeader().getDWOId();
0461 }
0462 void setDWOId(uint64_t NewID) { Header.setDWOId(NewID); }
0463
0464
0465
0466 Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset);
0467
0468
0469
0470
0471 Expected<DWARFAddressRangesVector> findRnglistFromIndex(uint32_t Index);
0472
0473
0474
0475
0476 std::optional<uint64_t> getRnglistOffset(uint32_t Index);
0477
0478 std::optional<uint64_t> getLoclistOffset(uint32_t Index);
0479
0480 Expected<DWARFAddressRangesVector> collectAddressRanges();
0481
0482 Expected<DWARFLocationExpressionsVector>
0483 findLoclistFromOffset(uint64_t Offset);
0484
0485
0486
0487
0488 DWARFDie getSubroutineForAddress(uint64_t Address);
0489
0490
0491
0492 DWARFDie getVariableForAddress(uint64_t Address);
0493
0494
0495
0496
0497 void getInlinedChainForAddress(uint64_t Address,
0498 SmallVectorImpl<DWARFDie> &InlinedChain);
0499
0500
0501 const DWARFUnitVector &getUnitVector() const { return UnitVector; }
0502
0503
0504
0505 unsigned getNumDIEs() {
0506 extractDIEsIfNeeded(false);
0507 return DieArray.size();
0508 }
0509
0510
0511
0512
0513
0514
0515
0516 uint32_t getDIEIndex(const DWARFDie &D) const {
0517 return getDIEIndex(D.getDebugInfoEntry());
0518 }
0519
0520
0521 DWARFDie getDIEAtIndex(unsigned Index) {
0522 return DWARFDie(this, getDebugInfoEntry(Index));
0523 }
0524
0525 DWARFDie getParent(const DWARFDebugInfoEntry *Die);
0526 DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
0527 DWARFDie getPreviousSibling(const DWARFDebugInfoEntry *Die);
0528 DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
0529 DWARFDie getLastChild(const DWARFDebugInfoEntry *Die);
0530
0531
0532
0533 DWARFDie getDIEForOffset(uint64_t Offset) {
0534 if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset))
0535 return DWARFDie(this, &DieArray[*DieIdx]);
0536
0537 return DWARFDie();
0538 }
0539
0540
0541
0542 std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
0543 extractDIEsIfNeeded(false);
0544 auto It =
0545 llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
0546 return DIE.getOffset() < Offset;
0547 });
0548 if (It != DieArray.end() && It->getOffset() == Offset)
0549 return It - DieArray.begin();
0550 return std::nullopt;
0551 }
0552
0553 uint32_t getLineTableOffset() const {
0554 if (auto IndexEntry = Header.getIndexEntry())
0555 if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LINE))
0556 return Contrib->getOffset32();
0557 return 0;
0558 }
0559
0560 die_iterator_range dies() {
0561 extractDIEsIfNeeded(false);
0562 return die_iterator_range(DieArray.begin(), DieArray.end());
0563 }
0564
0565 virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
0566
0567 Error tryExtractDIEsIfNeeded(bool CUDieOnly);
0568
0569 private:
0570
0571 size_t getDebugInfoSize() const {
0572 return Header.getLength() + Header.getUnitLengthFieldByteSize() -
0573 getHeaderSize();
0574 }
0575
0576
0577
0578 void extractDIEsIfNeeded(bool CUDieOnly);
0579
0580
0581 void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
0582 std::vector<DWARFDebugInfoEntry> &DIEs) const;
0583
0584
0585 void clearDIEs(bool KeepCUDie);
0586
0587
0588
0589
0590
0591
0592 bool parseDWO(StringRef AlternativeLocation = {});
0593 };
0594
0595 inline bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U) {
0596 return !U->isTypeUnit();
0597 }
0598
0599 }
0600
0601 #endif