35struct ContentDescriptor {
45 return Version >= 2 && Version <= 5;
50 switch (ContentType) {
51 case dwarf::DW_LNCT_timestamp:
54 case dwarf::DW_LNCT_size:
57 case dwarf::DW_LNCT_MD5:
60 case dwarf::DW_LNCT_LLVM_source:
73 uint16_t DwarfVersion = getVersion();
74 assert(DwarfVersion != 0 &&
75 "line table prologue has no dwarf version information");
76 if (DwarfVersion >= 5)
77 return FileIndex < FileNames.size();
78 return FileIndex != 0 && FileIndex <= FileNames.size();
81std::optional<uint64_t>
83 if (FileNames.empty())
85 uint16_t DwarfVersion = getVersion();
86 assert(DwarfVersion != 0 &&
87 "line table prologue has no dwarf version information");
89 if (DwarfVersion >= 5)
90 return FileNames.size() - 1;
91 return FileNames.size();
96 uint16_t DwarfVersion = getVersion();
97 assert(DwarfVersion != 0 &&
98 "line table prologue has no dwarf version information");
100 if (DwarfVersion >= 5)
101 return FileNames[
Index];
102 return FileNames[
Index - 1];
106 TotalLength = PrologueLength = 0;
108 MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
112 StandardOpcodeLengths.clear();
113 IncludeDirectories.clear();
119 if (!totalLengthIsValid())
122 OS <<
"Line table prologue:\n"
123 <<
format(
" total_length: 0x%0*" PRIx64
"\n", OffsetDumpWidth,
126 <<
format(
" version: %u\n", getVersion());
129 if (getVersion() >= 5)
130 OS <<
format(
" address_size: %u\n", getAddressSize())
131 <<
format(
" seg_select_size: %u\n", SegSelectorSize);
132 OS <<
format(
" prologue_length: 0x%0*" PRIx64
"\n", OffsetDumpWidth,
134 <<
format(
" min_inst_length: %u\n", MinInstLength)
135 <<
format(getVersion() >= 4 ?
"max_ops_per_inst: %u\n" :
"", MaxOpsPerInst)
136 <<
format(
" default_is_stmt: %u\n", DefaultIsStmt)
137 <<
format(
" line_base: %i\n", LineBase)
138 <<
format(
" line_range: %u\n", LineRange)
139 <<
format(
" opcode_base: %u\n", OpcodeBase);
141 for (
uint32_t I = 0;
I != StandardOpcodeLengths.size(); ++
I)
142 OS <<
formatv(
"standard_opcode_lengths[{0}] = {1}\n",
144 StandardOpcodeLengths[
I]);
146 if (!IncludeDirectories.empty()) {
148 uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
149 for (
uint32_t I = 0;
I != IncludeDirectories.size(); ++
I) {
150 OS <<
format(
"include_directories[%3u] = ",
I + DirBase);
151 IncludeDirectories[
I].dump(
OS, DumpOptions);
156 if (!FileNames.empty()) {
158 uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
161 OS <<
format(
"file_names[%3u]:\n",
I + FileBase);
164 OS <<
'\n' <<
format(
" dir_index: %" PRIu64
"\n", FileEntry.
DirIdx);
165 if (ContentTypes.HasMD5)
167 if (ContentTypes.HasModTime)
169 if (ContentTypes.HasLength)
171 if (ContentTypes.HasSource) {
175 else if ((*Source)[0]) {
190 std::vector<DWARFFormValue> &IncludeDirectories,
191 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
198 "include directories table was not null "
199 "terminated before the end of the prologue");
205 IncludeDirectories.push_back(Dir);
214 if (!Err &&
Name.empty())
228 "file names table was not null terminated before "
229 "the end of the prologue");
231 FileNames.push_back(FileEntry);
244 ContentDescriptors Descriptors;
245 int FormatCount = DebugLineData.
getU8(OffsetPtr, &Err);
246 bool HasPath =
false;
247 for (
int I = 0;
I != FormatCount && !Err; ++
I) {
248 ContentDescriptor Descriptor;
252 if (Descriptor.Type == dwarf::DW_LNCT_path)
256 Descriptors.push_back(Descriptor);
261 "failed to parse entry content descriptors: %s",
266 "failed to parse entry content descriptions"
267 " because no path was found");
276 std::vector<DWARFFormValue> &IncludeDirectories,
277 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
287 for (
auto Descriptor : *DirDescriptors) {
289 switch (Descriptor.Type) {
291 if (!
Value.extractValue(DebugLineData, OffsetPtr,
FormParams, &Ctx, U))
293 "failed to parse directory entry because "
294 "extracting the form value failed");
295 IncludeDirectories.push_back(
Value);
300 "failed to parse directory entry because "
301 "skipping the form value failed");
309 if (!FileDescriptors)
316 for (
auto Descriptor : *FileDescriptors) {
318 if (!
Value.extractValue(DebugLineData, OffsetPtr,
FormParams, &Ctx, U))
320 "failed to parse file entry because "
321 "extracting the form value failed");
322 switch (Descriptor.Type) {
326 case DW_LNCT_LLVM_source:
329 case DW_LNCT_directory_index:
332 case DW_LNCT_timestamp:
339 if (!
Value.getAsBlock() ||
Value.getAsBlock()->size() != 16)
342 "failed to parse file entry because the MD5 hash is invalid");
343 std::uninitialized_copy_n(
Value.getAsBlock()->begin(), 16,
350 FileNames.push_back(FileEntry);
357 sizeof(getVersion()) + sizeofPrologueLength();
358 if (getVersion() >= 5)
367 const uint64_t PrologueOffset = *OffsetPtr;
381 *OffsetPtr = Cursor.
tell();
384 "parsing line table prologue at offset 0x%8.8" PRIx64
385 ": unsupported version %" PRIu16,
386 PrologueOffset, getVersion());
389 if (getVersion() >= 5) {
392 const uint8_t PrologueAddrSize = getAddressSize();
394 if (DataAddrSize == 0) {
395 if (PrologueAddrSize != 4 && PrologueAddrSize != 8) {
398 "parsing line table prologue at offset 0x%8.8" PRIx64
399 ": invalid address size %" PRIu8,
400 PrologueOffset, PrologueAddrSize));
402 }
else if (DataAddrSize != PrologueAddrSize) {
405 "parsing line table prologue at offset 0x%8.8" PRIx64
": address "
406 "size %" PRIu8
" doesn't match architecture address size %" PRIu8,
407 PrologueOffset, PrologueAddrSize, DataAddrSize));
410 SegSelectorSize = DebugLineData.
getU8(Cursor);
415 const uint64_t EndPrologueOffset = PrologueLength + Cursor.
tell();
417 MinInstLength = DebugLineData.
getU8(Cursor);
418 if (getVersion() >= 4)
419 MaxOpsPerInst = DebugLineData.
getU8(Cursor);
420 DefaultIsStmt = DebugLineData.
getU8(Cursor);
421 LineBase = DebugLineData.
getU8(Cursor);
422 LineRange = DebugLineData.
getU8(Cursor);
423 OpcodeBase = DebugLineData.
getU8(Cursor);
425 if (Cursor && OpcodeBase == 0) {
431 "parsing line table prologue at offset 0x%8.8" PRIx64
432 " found opcode base of 0. Assuming no standard opcodes",
435 StandardOpcodeLengths.reserve(OpcodeBase - 1);
437 uint8_t OpLen = DebugLineData.
getU8(Cursor);
438 StandardOpcodeLengths.push_back(OpLen);
442 *OffsetPtr = Cursor.
tell();
449 "parsing line table prologue at offset 0x%8.8" PRIx64
": %s",
455 ContentTypes, IncludeDirectories, FileNames)
457 IncludeDirectories, FileNames);
462 "parsing line table prologue at 0x%8.8" PRIx64
463 " found an invalid directory or file table description at"
465 PrologueOffset, *OffsetPtr),
470 assert(*OffsetPtr <= EndPrologueOffset);
471 if (*OffsetPtr != EndPrologueOffset) {
474 "unknown data in line table prologue at offset 0x%8.8" PRIx64
475 ": parsing ended (at offset 0x%8.8" PRIx64
476 ") before reaching the prologue end at offset 0x%8.8" PRIx64,
477 PrologueOffset, *OffsetPtr, EndPrologueOffset));
488 EpilogueBegin =
false;
499 IsStmt = DefaultIsStmt;
504 EpilogueBegin =
false;
509 <<
"Address Line Column File ISA Discriminator OpIndex "
512 <<
"------------------ ------ ------ ------ --- ------------- ------- "
517 OS <<
format(
"0x%16.16" PRIx64
" %6u %6u",
Address.Address, Line, Column)
518 <<
format(
" %6u %3u %13u %7u ", File, Isa, Discriminator,
OpIndex)
519 << (IsStmt ?
" is_stmt" :
"") << (
BasicBlock ?
" basic_block" :
"")
520 << (PrologueEnd ?
" prologue_end" :
"")
521 << (EpilogueBegin ?
" epilogue_begin" :
"")
545 for (
const Row &R : Rows) {
561DWARFDebugLine::ParsingState::ParsingState(
565 resetRowAndSequence();
568void DWARFDebugLine::ParsingState::resetRowAndSequence() {
569 Row.reset(LineTable->Prologue.DefaultIsStmt);
573void DWARFDebugLine::ParsingState::appendRowToMatrix() {
574 unsigned RowNumber = LineTable->Rows.size();
575 if (Sequence.Empty) {
577 Sequence.Empty =
false;
578 Sequence.LowPC = Row.Address.Address;
579 Sequence.FirstRowIndex = RowNumber;
581 LineTable->appendRow(Row);
582 if (Row.EndSequence) {
584 Sequence.HighPC = Row.Address.Address;
585 Sequence.LastRowIndex = RowNumber + 1;
586 Sequence.SectionIndex = Row.Address.SectionIndex;
588 LineTable->appendSequence(Sequence);
596 LineTableConstIter Pos = LineTableMap.find(
Offset);
597 if (Pos != LineTableMap.end())
607 "offset 0x%8.8" PRIx64
608 " is not a valid debug line section offset",
611 std::pair<LineTableIter, bool> Pos =
616 LT->parse(DebugLineData, &
Offset, Ctx, U, RecoverableErrorHandler))
617 return std::move(Err);
624 LineTableMap.erase(
Offset);
629 if (Opcode < OpcodeBase)
635DWARFDebugLine::ParsingState::advanceAddrOpIndex(
uint64_t OperationAdvance,
642 if (ReportAdvanceAddrProblem && LineTable->Prologue.getVersion() >= 4 &&
643 LineTable->Prologue.MaxOpsPerInst == 0)
646 "line table program at offset 0x%8.8" PRIx64
647 " contains a %s opcode at offset 0x%8.8" PRIx64
648 ", but the prologue maximum_operations_per_instruction value is 0"
649 ", which is invalid. Assuming a value of 1 instead",
650 LineTableOffset, OpcodeName.
data(), OpcodeOffset));
656 if (ReportAdvanceAddrProblem && LineTable->Prologue.MaxOpsPerInst > 1)
659 "line table program at offset 0x%8.8" PRIx64
660 " contains a %s opcode at offset 0x%8.8" PRIx64
661 ", but the prologue maximum_operations_per_instruction value is %" PRId8
662 ", which is experimentally supported, so line number information "
664 LineTableOffset, OpcodeName.
data(), OpcodeOffset,
665 LineTable->Prologue.MaxOpsPerInst));
666 if (ReportAdvanceAddrProblem && LineTable->Prologue.MinInstLength == 0)
669 "line table program at offset 0x%8.8" PRIx64
670 " contains a %s opcode at offset 0x%8.8" PRIx64
671 ", but the prologue minimum_instruction_length value "
672 "is 0, which prevents any address advancing",
673 LineTableOffset, OpcodeName.
data(), OpcodeOffset));
674 ReportAdvanceAddrProblem =
false;
687 uint8_t MaxOpsPerInst =
688 std::max(LineTable->Prologue.MaxOpsPerInst, uint8_t{1});
690 uint64_t AddrOffset = ((Row.OpIndex + OperationAdvance) / MaxOpsPerInst) *
691 LineTable->Prologue.MinInstLength;
692 Row.Address.Address += AddrOffset;
694 uint8_t PrevOpIndex = Row.OpIndex;
695 Row.OpIndex = (Row.OpIndex + OperationAdvance) % MaxOpsPerInst;
696 int16_t OpIndexDelta =
static_cast<int16_t
>(Row.OpIndex) - PrevOpIndex;
698 return {AddrOffset, OpIndexDelta};
702DWARFDebugLine::ParsingState::advanceForOpcode(uint8_t Opcode,
704 assert(Opcode == DW_LNS_const_add_pc ||
705 Opcode >= LineTable->Prologue.OpcodeBase);
706 if (ReportBadLineRange && LineTable->Prologue.LineRange == 0) {
711 "line table program at offset 0x%8.8" PRIx64
712 " contains a %s opcode at offset 0x%8.8" PRIx64
713 ", but the prologue line_range value is 0. The "
714 "address and line will not be adjusted",
715 LineTableOffset, OpcodeName.
data(), OpcodeOffset));
716 ReportBadLineRange =
false;
719 uint8_t OpcodeValue = Opcode;
720 if (Opcode == DW_LNS_const_add_pc)
722 uint8_t AdjustedOpcode = OpcodeValue - LineTable->Prologue.OpcodeBase;
724 LineTable->Prologue.LineRange != 0
725 ? AdjustedOpcode / LineTable->Prologue.LineRange
727 AddrOpIndexDelta Advance =
728 advanceAddrOpIndex(OperationAdvance, Opcode, OpcodeOffset);
729 return {Advance.AddrOffset, Advance.OpIndexDelta, AdjustedOpcode};
733DWARFDebugLine::ParsingState::handleSpecialOpcode(uint8_t Opcode,
767 advanceForOpcode(Opcode, OpcodeOffset);
768 int32_t LineOffset = 0;
769 if (LineTable->Prologue.LineRange != 0)
771 LineTable->Prologue.LineBase +
772 (AddrAdvanceResult.
AdjustedOpcode % LineTable->Prologue.LineRange);
773 Row.Line += LineOffset;
774 return {AddrAdvanceResult.
AddrDelta, LineOffset,
794 assert((
OS || !
Verbose) &&
"cannot have verbose output without stream");
795 const uint64_t DebugLineOffset = *OffsetPtr;
800 Prologue.
parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U);
819 assert(DebugLineData.
size() > DebugLineOffset &&
820 "prologue parsing should handle invalid offset");
821 uint64_t BytesRemaining = DebugLineData.
size() - DebugLineOffset;
822 RecoverableErrorHandler(
824 "line table program with offset 0x%8.8" PRIx64
825 " has length 0x%8.8" PRIx64
" but only 0x%8.8" PRIx64
826 " bytes are available",
827 DebugLineOffset, ProgramLength, BytesRemaining));
829 ProgramLength = BytesRemaining;
834 const uint64_t EndOffset = DebugLineOffset + ProgramLength;
844 ParsingState State(
this, DebugLineOffset, RecoverableErrorHandler);
847 if (
OS && *OffsetPtr < EndOffset) {
851 bool TombstonedAddress =
false;
853 if (!TombstonedAddress) {
860 State.appendRowToMatrix();
863 while (*OffsetPtr < EndOffset) {
867 *
OS <<
format(
"0x%08.08" PRIx64
": ", *OffsetPtr);
870 uint8_t Opcode = TableData.
getU8(Cursor);
871 size_t RowCount = Rows.size();
874 *
OS <<
format(
"%02.02" PRIx8
" ", Opcode);
885 *
OS <<
"Badly formed extended line op (length 0)\n";
889 RecoverableErrorHandler(Cursor.
takeError());
891 *OffsetPtr = Cursor.
tell();
895 uint8_t SubOpcode = TableData.
getU8(Cursor);
902 case DW_LNE_end_sequence:
910 State.Row.EndSequence =
true;
915 State.resetRowAndSequence();
918 case DW_LNE_set_address:
931 uint64_t OpcodeAddressSize = Len - 1;
932 if (ExtractorAddressSize != OpcodeAddressSize &&
933 ExtractorAddressSize != 0)
936 "mismatching address size at offset 0x%8.8" PRIx64
937 " expected 0x%2.2" PRIx8
" found 0x%2.2" PRIx64,
938 ExtOffset, ExtractorAddressSize, Len - 1));
943 if (OpcodeAddressSize != 1 && OpcodeAddressSize != 2 &&
944 OpcodeAddressSize != 4 && OpcodeAddressSize != 8) {
947 "address size 0x%2.2" PRIx64
948 " of DW_LNE_set_address opcode at offset 0x%8.8" PRIx64
950 OpcodeAddressSize, ExtOffset));
951 TableData.
skip(Cursor, OpcodeAddressSize);
955 Cursor, &State.Row.Address.SectionIndex);
956 State.Row.OpIndex = 0;
960 TombstonedAddress = State.Row.Address.Address == Tombstone;
963 if (ExtractorAddressSize != 0)
970 State.Row.Address.Address);
976 case DW_LNE_define_file:
1007 *
OS <<
" (" <<
Name <<
", dir=" << FileEntry.
DirIdx <<
", mod_time="
1009 <<
", length=" << FileEntry.
Length <<
")";
1013 case DW_LNE_set_discriminator:
1014 State.Row.Discriminator = TableData.
getULEB128(Cursor);
1016 *
OS <<
" (" << State.Row.Discriminator <<
")";
1021 *
OS <<
format(
"Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
1022 <<
format(
" length %" PRIx64, Len);
1025 TableData.
skip(Cursor, Len - 1);
1033 if (Cursor && Cursor.
tell() !=
End)
1036 "unexpected line op length at offset 0x%8.8" PRIx64
1037 " expected 0x%2.2" PRIx64
" found 0x%2.2" PRIx64,
1038 ExtOffset, Len, Cursor.
tell() - ExtOffset));
1041 uint8_t Byte = TableData.
getU8(ByteCursor);
1043 *
OS <<
" (<parsing error>";
1045 *
OS <<
format(
" %2.2" PRIx8, Byte);
1046 Byte = TableData.
getU8(ByteCursor);
1047 }
while (ByteCursor);
1068 case DW_LNS_advance_pc:
1072 if (std::optional<uint64_t> Operand =
1073 parseULEB128<uint64_t>(TableData, Cursor)) {
1075 State.advanceAddrOpIndex(*Operand, Opcode, OpcodeOffset);
1082 case DW_LNS_advance_line:
1086 int64_t LineDelta = TableData.
getSLEB128(Cursor);
1088 State.Row.Line += LineDelta;
1090 *
OS <<
" (" << State.Row.Line <<
")";
1095 case DW_LNS_set_file:
1098 if (std::optional<uint16_t> File =
1099 parseULEB128<uint16_t>(TableData, Cursor)) {
1100 State.Row.File = *File;
1102 *
OS <<
" (" << State.Row.File <<
")";
1106 case DW_LNS_set_column:
1109 if (std::optional<uint16_t> Column =
1110 parseULEB128<uint16_t>(TableData, Cursor)) {
1111 State.Row.Column = *Column;
1113 *
OS <<
" (" << State.Row.Column <<
")";
1117 case DW_LNS_negate_stmt:
1120 State.Row.IsStmt = !State.Row.IsStmt;
1123 case DW_LNS_set_basic_block:
1126 State.Row.BasicBlock =
true;
1129 case DW_LNS_const_add_pc:
1143 State.advanceForOpcode(Opcode, OpcodeOffset);
1145 *
OS <<
format(
" (addr += 0x%16.16" PRIx64
", op-index += %" PRIu8
1151 case DW_LNS_fixed_advance_pc:
1165 State.Row.Address.Address += PCOffset;
1166 State.Row.OpIndex = 0;
1168 *
OS <<
format(
" (addr += 0x%4.4" PRIx16
", op-index = 0)",
1174 case DW_LNS_set_prologue_end:
1177 State.Row.PrologueEnd =
true;
1180 case DW_LNS_set_epilogue_begin:
1183 State.Row.EpilogueBegin =
true;
1186 case DW_LNS_set_isa:
1189 if (std::optional<uint8_t> Isa =
1190 parseULEB128<uint8_t>(TableData, Cursor)) {
1191 State.Row.Isa = *Isa;
1193 *
OS <<
" (" << (
uint64_t)State.Row.Isa <<
")";
1204 *
OS <<
"Unrecognized standard opcode";
1207 for (uint8_t
I = 0;
I < OpcodeLength; ++
I) {
1208 if (std::optional<uint64_t>
Value =
1209 parseULEB128<uint64_t>(TableData, Cursor))
1215 *
OS <<
" (operands: ";
1230 *OffsetPtr = Cursor.
tell();
1234 State.handleSpecialOpcode(Opcode, OpcodeOffset);
1237 *
OS <<
"address += " << Delta.
Address <<
", line += " << Delta.
Line
1238 <<
", op-index += " << Delta.
OpIndex;
1240 *OffsetPtr = Cursor.
tell();
1245 if (
Verbose && Rows.size() == RowCount)
1252 if (!Cursor && Opcode != 0) {
1259 RecoverableErrorHandler(Cursor.
takeError());
1262 if (!State.Sequence.Empty)
1265 "last sequence in debug line table at offset 0x%8.8" PRIx64
1266 " is not terminated",
1270 if (!Sequences.empty()) {
1288uint32_t DWARFDebugLine::LineTable::findRowInSeq(
1292 return UnknownRowIndex;
1308 RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1,
Row,
1312 return RowPos - Rows.begin();
1317 bool *IsApproximateLine)
const {
1322 if (Result != UnknownRowIndex ||
1328 return lookupAddressImpl(
Address, IsApproximateLine);
1333 bool *IsApproximateLine)
const {
1334 assert((!IsApproximateLine || !*IsApproximateLine) &&
1335 "Make sure IsApproximateLine is appropriately "
1336 "initialized, if provided");
1343 if (It == Sequences.end() || It->SectionIndex !=
Address.SectionIndex)
1344 return UnknownRowIndex;
1347 if (RowIndex == UnknownRowIndex || !IsApproximateLine)
1351 uint32_t ApproxRowIndex = RowIndex;
1353 for (; ApproxRowIndex >= It->FirstRowIndex; --ApproxRowIndex) {
1354 if (Rows[ApproxRowIndex].Line)
1355 return ApproxRowIndex;
1356 *IsApproximateLine =
true;
1359 if (ApproxRowIndex < It->FirstRowIndex)
1360 *IsApproximateLine =
false;
1367 std::vector<uint32_t> &Result)
const {
1370 if (lookupAddressRangeImpl(
Address,
Size, Result))
1378 return lookupAddressRangeImpl(
Address,
Size, Result);
1381bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
1383 std::vector<uint32_t> &Result)
const {
1384 if (Sequences.empty())
1391 SequenceIter LastSeq = Sequences.end();
1394 if (SeqPos == LastSeq || !SeqPos->containsPC(
Address))
1397 SequenceIter StartPos = SeqPos;
1402 while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
1407 if (SeqPos == StartPos)
1408 FirstRowIndex = findRowInSeq(CurSeq,
Address);
1412 findRowInSeq(CurSeq, {EndAddr - 1,
Address.SectionIndex});
1413 if (LastRowIndex == UnknownRowIndex)
1416 assert(FirstRowIndex != UnknownRowIndex);
1417 assert(LastRowIndex != UnknownRowIndex);
1419 for (
uint32_t I = FirstRowIndex;
I <= LastRowIndex; ++
I) {
1420 Result.push_back(
I);
1429std::optional<StringRef>
1430DWARFDebugLine::LineTable::getSourceByIndex(
uint64_t FileIndex,
1432 if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex))
1433 return std::nullopt;
1434 const FileNameEntry &
Entry = Prologue.getFileNameEntry(FileIndex);
1437 return std::nullopt;
1451 if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
1458 if (Kind == FileLineInfoKind::RawValue ||
1460 Result = std::string(FileName);
1463 if (Kind == FileLineInfoKind::BaseNameOnly) {
1471 if (getVersion() >= 5) {
1474 if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) &&
1475 Entry.DirIdx < IncludeDirectories.size())
1478 if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size())
1486 if (Kind == FileLineInfoKind::AbsoluteFilePath &&
1487 (getVersion() < 5 || Entry.DirIdx != 0) && !CompDir.
empty() &&
1491 assert((Kind == FileLineInfoKind::AbsoluteFilePath ||
1492 Kind == FileLineInfoKind::RelativeFilePath) &&
1493 "invalid FileLineInfo Kind");
1497 Result = std::string(FilePath);
1506 lookupAddress(
Address, Approximate ? &Result.IsApproximateLine :
nullptr);
1507 if (RowIndex == -1U)
1510 const auto &
Row = Rows[RowIndex];
1511 if (!getFileNameByIndex(
Row.
File, CompDir, Kind, Result.FileName))
1516 Result.Source = getSourceByIndex(
Row.
File, Kind);
1545 for (
const auto &U : Units)
1546 if (
auto CUDIE = U->getUnitDIE())
1548 LineToUnit.insert(std::make_pair(*StmtOffset, &*U));
1555 : DebugLineData(
Data), Context(
C) {
1562 return TotalLength != 0u;
1570 "parsing should have terminated");
1574 if (
Error Err = LT.parse(DebugLineData, &
Offset, Context, U,
1576 UnrecoverableErrorHandler(std::move(Err));
1577 moveToNextTable(OldOffset, LT.Prologue);
1585 "parsing should have terminated");
1589 if (
Error Err = LT.Prologue.parse(DebugLineData, &
Offset,
1590 RecoverableErrorHandler, Context, U))
1591 UnrecoverableErrorHandler(std::move(Err));
1592 moveToNextTable(OldOffset, LT.Prologue);
1597 auto It = LineToUnit.find(
Offset);
1598 if (It != LineToUnit.end())
1604bool DWARFDebugLine::SectionParser::hasValidVersion(
uint64_t Offset) {
1619void DWARFDebugLine::SectionParser::moveToNextTable(
uint64_t OldOffset,
1620 const Prologue &
P) {
1624 if (!
P.totalLengthIsValid()) {
1629 Offset = OldOffset +
P.TotalLength +
P.sizeofTotalLength();
1637 if (hasValidVersion(
Offset))
1643 for (
unsigned Align : {4, 8}) {
1652 if (hasValidVersion(AlignedOffset)) {
static void clear(coro::Shape &Shape)
static Error parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const dwarf::FormParams &FormParams, const DWARFContext &Ctx, const DWARFUnit *U, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector< DWARFFormValue > &IncludeDirectories, std::vector< DWARFDebugLine::FileNameEntry > &FileNames)
static Error parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector< DWARFFormValue > &IncludeDirectories, std::vector< DWARFDebugLine::FileNameEntry > &FileNames)
static llvm::Expected< ContentDescriptors > parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, DWARFDebugLine::ContentTypeTracker *ContentTypes)
static DWARFDebugLine::SectionParser::LineToUnitMap buildLineToUnitMap(DWARFUnitVector::iterator_range Units)
static bool versionIsSupported(uint16_t Version)
static StringRef getOpcodeName(uint8_t Opcode, uint8_t OpcodeBase)
static std::optional< T > parseULEB128(DWARFDataExtractor &Data, DataExtractor::Cursor &Cursor)
Parse a ULEB128 using the specified Cursor.
This file contains constants used for implementing Dwarf debug support.
static fatal_error_handler_t ErrorHandler
@ EndSequence
End of the line table.
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
This file defines the SmallVector class.
LLVM Basic Block Representation.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
void skip(function_ref< void(Error)> RecoverableErrorHandler, function_ref< void(Error)> UnrecoverableErrorHandler)
Skip the current line table and go to the following line table (if present) immediately.
std::map< uint64_t, DWARFUnit * > LineToUnitMap
LineTable parseNext(function_ref< void(Error)> RecoverableErrorHandler, function_ref< void(Error)> UnrecoverableErrorHandler, raw_ostream *OS=nullptr, bool Verbose=false)
Get the next line table from the section.
SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, DWARFUnitVector::iterator_range Units)
void clearLineTable(uint64_t Offset)
Expected< const LineTable * > getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, function_ref< void(Error)> RecoverableErrorHandler)
const LineTable * getLineTable(uint64_t Offset) const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
StringRef LNExtendedString(unsigned Encoding)
StringRef FormatString(DwarfFormat Format)
StringRef LNStandardString(unsigned Standard)
@ C
The default llvm calling convention, compatible with C.
bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
LineNumberOps
Line Number Standard Opcode Encodings.
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
uint64_t computeTombstoneAddress(uint8_t AddressByteSize)
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
void sort(IteratorTy Start, IteratorTy End)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
void consumeError(Error Err)
Consume a Error without doing anything.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Container for dump options that control which debug information will be dumped.
A format-neutral container for source line information.
Tracks which optional content types are present in a DWARF file name entry format.
bool HasLength
Whether filename entries provide a file size.
bool HasSource
For v5, whether filename entries provide source text.
bool HasModTime
Whether filename entries provide a modification timestamp.
bool HasMD5
For v5, whether filename entries provide an MD5 checksum.
void trackContentType(dwarf::LineNumberEntryFormat ContentType)
Update tracked content types with ContentType.
uint32_t lookupAddress(object::SectionedAddress Address, bool *IsApproximateLine=nullptr) const
Returns the index of the row with file/line info for a given address, or UnknownRowIndex if there is ...
bool getDirectoryForEntry(const FileNameEntry &Entry, std::string &Directory) const
Extracts directory name by its Entry in include directories table in prologue.
bool getFileLineInfoForAddress(object::SectionedAddress Address, bool Approximate, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const
Fills the Result argument with the file and line information corresponding to Address.
Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, const DWARFContext &Ctx, const DWARFUnit *U, function_ref< void(Error)> RecoverableErrorHandler, raw_ostream *OS=nullptr, bool Verbose=false)
Parse prologue and all rows.
bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector< uint32_t > &Result) const
void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const
bool hasFileAtIndex(uint64_t FileIndex) const
void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const
uint32_t sizeofTotalLength() const
uint16_t getVersion() const
std::optional< uint64_t > getLastValidFileIndex() const
Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr, function_ref< void(Error)> RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U=nullptr)
std::vector< DWARFFormValue > IncludeDirectories
uint8_t OpcodeBase
The number assigned to the first special opcode.
std::vector< uint8_t > StandardOpcodeLengths
bool totalLengthIsValid() const
uint8_t getAddressSize() const
const llvm::DWARFDebugLine::FileNameEntry & getFileNameEntry(uint64_t Index) const
Get DWARF-version aware access to the file name entry at the provided index.
bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result, sys::path::Style Style=sys::path::Style::native) const
uint64_t TotalLength
The size in bytes of the statement information for this compilation unit (not including the total_len...
uint64_t getLength() const
Length of the prologue in bytes.
std::vector< FileNameEntry > FileNames
Standard .debug_line state machine structure.
static bool orderByAddress(const Row &LHS, const Row &RHS)
uint32_t Line
An unsigned integer indicating a source line number.
uint16_t File
An unsigned integer indicating the identity of the source file corresponding to a machine instruction...
uint32_t Discriminator
An unsigned integer representing the DWARF path discriminator value for this location.
object::SectionedAddress Address
The program-counter value corresponding to a machine instruction generated by the compiler and sectio...
void postAppend()
Called after a row is appended to the matrix.
uint16_t Column
An unsigned integer indicating a column number within a source line.
static void dumpTableHeader(raw_ostream &OS, unsigned Indent)
void reset(bool DefaultIsStmt)
Row(bool DefaultIsStmt=false)
void dump(raw_ostream &OS) const
Represents a series of contiguous machine instructions.
static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS)
bool containsPC(object::SectionedAddress PC) const
uint64_t SectionIndex
If relocation information is present then this is the index of the section which contains above addre...
SmallString< 32 > digest() const
static const uint64_t UndefSection