File indexing completed on 2026-05-10 08:43:41
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H
0010 #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLINE_H
0011
0012 #include "llvm/ADT/StringRef.h"
0013 #include "llvm/BinaryFormat/Dwarf.h"
0014 #include "llvm/DebugInfo/DIContext.h"
0015 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
0016 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
0017 #include "llvm/Support/MD5.h"
0018 #include "llvm/Support/Path.h"
0019 #include <cstdint>
0020 #include <map>
0021 #include <string>
0022 #include <vector>
0023
0024 namespace llvm {
0025
0026 class raw_ostream;
0027
0028 class DWARFDebugLine {
0029 public:
0030 struct FileNameEntry {
0031 FileNameEntry() = default;
0032
0033 DWARFFormValue Name;
0034 uint64_t DirIdx = 0;
0035 uint64_t ModTime = 0;
0036 uint64_t Length = 0;
0037 MD5::MD5Result Checksum;
0038 DWARFFormValue Source;
0039 };
0040
0041
0042
0043 struct ContentTypeTracker {
0044 ContentTypeTracker() = default;
0045
0046
0047 bool HasModTime = false;
0048
0049 bool HasLength = false;
0050
0051 bool HasMD5 = false;
0052
0053 bool HasSource = false;
0054
0055
0056 void trackContentType(dwarf::LineNumberEntryFormat ContentType);
0057 };
0058
0059 struct Prologue {
0060 Prologue();
0061
0062
0063
0064 uint64_t TotalLength;
0065
0066
0067
0068 dwarf::FormParams FormParams;
0069
0070
0071 uint64_t PrologueLength;
0072
0073 uint8_t SegSelectorSize;
0074
0075
0076
0077 uint8_t MinInstLength;
0078
0079
0080 uint8_t MaxOpsPerInst;
0081
0082 uint8_t DefaultIsStmt;
0083
0084 int8_t LineBase;
0085
0086 uint8_t LineRange;
0087
0088 uint8_t OpcodeBase;
0089
0090 ContentTypeTracker ContentTypes;
0091 std::vector<uint8_t> StandardOpcodeLengths;
0092 std::vector<DWARFFormValue> IncludeDirectories;
0093 std::vector<FileNameEntry> FileNames;
0094
0095 const dwarf::FormParams getFormParams() const { return FormParams; }
0096 uint16_t getVersion() const { return FormParams.Version; }
0097 uint8_t getAddressSize() const { return FormParams.AddrSize; }
0098 bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
0099
0100 uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
0101
0102 uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
0103
0104 bool totalLengthIsValid() const;
0105
0106
0107 uint64_t getLength() const;
0108
0109
0110
0111 const llvm::DWARFDebugLine::FileNameEntry &
0112 getFileNameEntry(uint64_t Index) const;
0113
0114 bool hasFileAtIndex(uint64_t FileIndex) const;
0115
0116 std::optional<uint64_t> getLastValidFileIndex() const;
0117
0118 bool
0119 getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
0120 DILineInfoSpecifier::FileLineInfoKind Kind,
0121 std::string &Result,
0122 sys::path::Style Style = sys::path::Style::native) const;
0123
0124 void clear();
0125 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
0126 Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr,
0127 function_ref<void(Error)> RecoverableErrorHandler,
0128 const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
0129 };
0130
0131
0132 struct Row {
0133 explicit Row(bool DefaultIsStmt = false);
0134
0135
0136 void postAppend();
0137 void reset(bool DefaultIsStmt);
0138 void dump(raw_ostream &OS) const;
0139
0140 static void dumpTableHeader(raw_ostream &OS, unsigned Indent);
0141
0142 static bool orderByAddress(const Row &LHS, const Row &RHS) {
0143 return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) <
0144 std::tie(RHS.Address.SectionIndex, RHS.Address.Address);
0145 }
0146
0147
0148
0149
0150
0151
0152 object::SectionedAddress Address;
0153
0154
0155
0156 uint32_t Line;
0157
0158
0159
0160 uint16_t Column;
0161
0162
0163 uint16_t File;
0164
0165
0166 uint32_t Discriminator;
0167
0168
0169 uint8_t Isa;
0170
0171
0172
0173 uint8_t OpIndex;
0174
0175
0176 uint8_t IsStmt : 1,
0177
0178
0179 BasicBlock : 1,
0180
0181
0182
0183 EndSequence : 1,
0184
0185
0186
0187 PrologueEnd : 1,
0188
0189
0190
0191 EpilogueBegin : 1;
0192 };
0193
0194
0195
0196
0197 struct Sequence {
0198 Sequence();
0199
0200
0201
0202 uint64_t LowPC;
0203 uint64_t HighPC;
0204
0205
0206
0207 uint64_t SectionIndex;
0208 unsigned FirstRowIndex;
0209 unsigned LastRowIndex;
0210 bool Empty;
0211
0212 void reset();
0213
0214 static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS) {
0215 return std::tie(LHS.SectionIndex, LHS.HighPC) <
0216 std::tie(RHS.SectionIndex, RHS.HighPC);
0217 }
0218
0219 bool isValid() const {
0220 return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex);
0221 }
0222
0223 bool containsPC(object::SectionedAddress PC) const {
0224 return SectionIndex == PC.SectionIndex &&
0225 (LowPC <= PC.Address && PC.Address < HighPC);
0226 }
0227 };
0228
0229 struct LineTable {
0230 LineTable();
0231
0232
0233 const uint32_t UnknownRowIndex = UINT32_MAX;
0234
0235 void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); }
0236
0237 void appendSequence(const DWARFDebugLine::Sequence &S) {
0238 Sequences.push_back(S);
0239 }
0240
0241
0242
0243 uint32_t lookupAddress(object::SectionedAddress Address,
0244 bool *IsApproximateLine = nullptr) const;
0245
0246 bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size,
0247 std::vector<uint32_t> &Result) const;
0248
0249 bool hasFileAtIndex(uint64_t FileIndex) const {
0250 return Prologue.hasFileAtIndex(FileIndex);
0251 }
0252
0253 std::optional<uint64_t> getLastValidFileIndex() const {
0254 return Prologue.getLastValidFileIndex();
0255 }
0256
0257
0258
0259
0260
0261
0262 bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
0263 DILineInfoSpecifier::FileLineInfoKind Kind,
0264 std::string &Result) const {
0265 return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result);
0266 }
0267
0268
0269
0270 bool getFileLineInfoForAddress(object::SectionedAddress Address,
0271 bool Approximate, const char *CompDir,
0272 DILineInfoSpecifier::FileLineInfoKind Kind,
0273 DILineInfo &Result) const;
0274
0275
0276
0277 bool getDirectoryForEntry(const FileNameEntry &Entry,
0278 std::string &Directory) const;
0279
0280 void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
0281 void clear();
0282
0283
0284 Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
0285 const DWARFContext &Ctx, const DWARFUnit *U,
0286 function_ref<void(Error)> RecoverableErrorHandler,
0287 raw_ostream *OS = nullptr, bool Verbose = false);
0288
0289 using RowVector = std::vector<Row>;
0290 using RowIter = RowVector::const_iterator;
0291 using SequenceVector = std::vector<Sequence>;
0292 using SequenceIter = SequenceVector::const_iterator;
0293
0294 struct Prologue Prologue;
0295 RowVector Rows;
0296 SequenceVector Sequences;
0297
0298 private:
0299 uint32_t findRowInSeq(const DWARFDebugLine::Sequence &Seq,
0300 object::SectionedAddress Address) const;
0301 std::optional<StringRef>
0302 getSourceByIndex(uint64_t FileIndex,
0303 DILineInfoSpecifier::FileLineInfoKind Kind) const;
0304
0305 uint32_t lookupAddressImpl(object::SectionedAddress Address,
0306 bool *IsApproximateLine = nullptr) const;
0307
0308 bool lookupAddressRangeImpl(object::SectionedAddress Address, uint64_t Size,
0309 std::vector<uint32_t> &Result) const;
0310 };
0311
0312 const LineTable *getLineTable(uint64_t Offset) const;
0313 Expected<const LineTable *>
0314 getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset,
0315 const DWARFContext &Ctx, const DWARFUnit *U,
0316 function_ref<void(Error)> RecoverableErrorHandler);
0317 void clearLineTable(uint64_t Offset);
0318
0319
0320 class SectionParser {
0321 public:
0322 using LineToUnitMap = std::map<uint64_t, DWARFUnit *>;
0323
0324 SectionParser(DWARFDataExtractor &Data, const DWARFContext &C,
0325 DWARFUnitVector::iterator_range Units);
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338 LineTable parseNext(function_ref<void(Error)> RecoverableErrorHandler,
0339 function_ref<void(Error)> UnrecoverableErrorHandler,
0340 raw_ostream *OS = nullptr, bool Verbose = false);
0341
0342
0343
0344
0345
0346
0347
0348
0349 void skip(function_ref<void(Error)> RecoverableErrorHandler,
0350 function_ref<void(Error)> UnrecoverableErrorHandler);
0351
0352
0353
0354
0355
0356 bool done() const { return Done; }
0357
0358
0359 uint64_t getOffset() const { return Offset; }
0360
0361 private:
0362 DWARFUnit *prepareToParse(uint64_t Offset);
0363 void moveToNextTable(uint64_t OldOffset, const Prologue &P);
0364 bool hasValidVersion(uint64_t Offset);
0365
0366 LineToUnitMap LineToUnit;
0367
0368 DWARFDataExtractor &DebugLineData;
0369 const DWARFContext &Context;
0370 uint64_t Offset = 0;
0371 bool Done = false;
0372 };
0373
0374 private:
0375 struct ParsingState {
0376 ParsingState(struct LineTable *LT, uint64_t TableOffset,
0377 function_ref<void(Error)> ErrorHandler);
0378
0379 void resetRowAndSequence();
0380 void appendRowToMatrix();
0381
0382 struct AddrOpIndexDelta {
0383 uint64_t AddrOffset;
0384 int16_t OpIndexDelta;
0385 };
0386
0387
0388
0389 AddrOpIndexDelta advanceAddrOpIndex(uint64_t OperationAdvance,
0390 uint8_t Opcode, uint64_t OpcodeOffset);
0391
0392 struct OpcodeAdvanceResults {
0393 uint64_t AddrDelta;
0394 int16_t OpIndexDelta;
0395 uint8_t AdjustedOpcode;
0396 };
0397
0398
0399
0400 OpcodeAdvanceResults advanceForOpcode(uint8_t Opcode,
0401 uint64_t OpcodeOffset);
0402
0403 struct SpecialOpcodeDelta {
0404 uint64_t Address;
0405 int32_t Line;
0406 int16_t OpIndex;
0407 };
0408
0409
0410
0411 SpecialOpcodeDelta handleSpecialOpcode(uint8_t Opcode,
0412 uint64_t OpcodeOffset);
0413
0414
0415 struct LineTable *LineTable;
0416 struct Row Row;
0417 struct Sequence Sequence;
0418
0419 private:
0420 uint64_t LineTableOffset;
0421
0422 bool ReportAdvanceAddrProblem = true;
0423 bool ReportBadLineRange = true;
0424 function_ref<void(Error)> ErrorHandler;
0425 };
0426
0427 using LineTableMapTy = std::map<uint64_t, LineTable>;
0428 using LineTableIter = LineTableMapTy::iterator;
0429 using LineTableConstIter = LineTableMapTy::const_iterator;
0430
0431 LineTableMapTy LineTableMap;
0432 };
0433
0434 }
0435
0436 #endif