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);
165 <<
format(
" dir_index: %" PRIu64
"\n", FileEntry.
DirIdx);
166 if (ContentTypes.HasMD5)
168 if (ContentTypes.HasModTime)
170 if (ContentTypes.HasLength)
172 if (ContentTypes.HasSource) {
176 else if ((*Source)[0]) {
191 std::vector<DWARFFormValue> &IncludeDirectories,
192 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
199 "include directories table was not null "
200 "terminated before the end of the prologue");
206 IncludeDirectories.push_back(Dir);
215 if (!Err &&
Name.empty())
229 "file names table was not null terminated before "
230 "the end of the prologue");
232 FileNames.push_back(FileEntry);
245 ContentDescriptors Descriptors;
246 int FormatCount = DebugLineData.
getU8(OffsetPtr, &Err);
247 bool HasPath =
false;
248 for (
int I = 0;
I != FormatCount && !Err; ++
I) {
249 ContentDescriptor Descriptor;
253 if (Descriptor.Type == dwarf::DW_LNCT_path)
257 Descriptors.push_back(Descriptor);
262 "failed to parse entry content descriptors: %s",
267 "failed to parse entry content descriptions"
268 " because no path was found");
277 std::vector<DWARFFormValue> &IncludeDirectories,
278 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
288 for (
auto Descriptor : *DirDescriptors) {
290 switch (Descriptor.Type) {
292 if (!
Value.extractValue(DebugLineData, OffsetPtr,
FormParams, &Ctx, U))
294 "failed to parse directory entry because "
295 "extracting the form value failed");
296 IncludeDirectories.push_back(
Value);
301 "failed to parse directory entry because "
302 "skipping the form value failed");
310 if (!FileDescriptors)
317 for (
auto Descriptor : *FileDescriptors) {
319 if (!
Value.extractValue(DebugLineData, OffsetPtr,
FormParams, &Ctx, U))
321 "failed to parse file entry because "
322 "extracting the form value failed");
323 switch (Descriptor.Type) {
327 case DW_LNCT_LLVM_source:
330 case DW_LNCT_directory_index:
333 case DW_LNCT_timestamp:
340 if (!
Value.getAsBlock() ||
Value.getAsBlock()->size() != 16)
343 "failed to parse file entry because the MD5 hash is invalid");
344 std::uninitialized_copy_n(
Value.getAsBlock()->begin(), 16,
351 FileNames.push_back(FileEntry);
358 sizeof(getVersion()) + sizeofPrologueLength();
359 if (getVersion() >= 5)
368 const uint64_t PrologueOffset = *OffsetPtr;
382 *OffsetPtr = Cursor.
tell();
385 "parsing line table prologue at offset 0x%8.8" PRIx64
386 ": unsupported version %" PRIu16,
387 PrologueOffset, getVersion());
390 if (getVersion() >= 5) {
393 const uint8_t PrologueAddrSize = getAddressSize();
395 if (DataAddrSize == 0) {
396 if (PrologueAddrSize != 4 && PrologueAddrSize != 8) {
399 "parsing line table prologue at offset 0x%8.8" PRIx64
400 ": invalid address size %" PRIu8,
401 PrologueOffset, PrologueAddrSize));
403 }
else if (DataAddrSize != PrologueAddrSize) {
406 "parsing line table prologue at offset 0x%8.8" PRIx64
": address "
407 "size %" PRIu8
" doesn't match architecture address size %" PRIu8,
408 PrologueOffset, PrologueAddrSize, DataAddrSize));
411 SegSelectorSize = DebugLineData.
getU8(Cursor);
416 const uint64_t EndPrologueOffset = PrologueLength + Cursor.
tell();
418 MinInstLength = DebugLineData.
getU8(Cursor);
419 if (getVersion() >= 4)
420 MaxOpsPerInst = DebugLineData.
getU8(Cursor);
421 DefaultIsStmt = DebugLineData.
getU8(Cursor);
422 LineBase = DebugLineData.
getU8(Cursor);
423 LineRange = DebugLineData.
getU8(Cursor);
424 OpcodeBase = DebugLineData.
getU8(Cursor);
426 if (Cursor && OpcodeBase == 0) {
432 "parsing line table prologue at offset 0x%8.8" PRIx64
433 " found opcode base of 0. Assuming no standard opcodes",
436 StandardOpcodeLengths.reserve(OpcodeBase - 1);
438 uint8_t OpLen = DebugLineData.
getU8(Cursor);
439 StandardOpcodeLengths.push_back(OpLen);
443 *OffsetPtr = Cursor.
tell();
450 "parsing line table prologue at offset 0x%8.8" PRIx64
": %s",
456 ContentTypes, IncludeDirectories, FileNames)
458 IncludeDirectories, FileNames);
463 "parsing line table prologue at 0x%8.8" PRIx64
464 " found an invalid directory or file table description at"
466 PrologueOffset, *OffsetPtr),
471 assert(*OffsetPtr <= EndPrologueOffset);
472 if (*OffsetPtr != EndPrologueOffset) {
475 "unknown data in line table prologue at offset 0x%8.8" PRIx64
476 ": parsing ended (at offset 0x%8.8" PRIx64
477 ") before reaching the prologue end at offset 0x%8.8" PRIx64,
478 PrologueOffset, *OffsetPtr, EndPrologueOffset));
489 EpilogueBegin =
false;
500 IsStmt = DefaultIsStmt;
505 EpilogueBegin =
false;
510 <<
"Address Line Column File ISA Discriminator OpIndex "
513 <<
"------------------ ------ ------ ------ --- ------------- ------- "
518 OS <<
format(
"0x%16.16" PRIx64
" %6u %6u",
Address.Address, Line, Column)
519 <<
format(
" %6u %3u %13u %7u ", File, Isa, Discriminator,
OpIndex)
520 << (IsStmt ?
" is_stmt" :
"") << (
BasicBlock ?
" basic_block" :
"")
521 << (PrologueEnd ?
" prologue_end" :
"")
522 << (EpilogueBegin ?
" epilogue_begin" :
"")
546 for (
const Row &R : Rows) {
562DWARFDebugLine::ParsingState::ParsingState(
566 resetRowAndSequence();
569void DWARFDebugLine::ParsingState::resetRowAndSequence() {
570 Row.reset(LineTable->Prologue.DefaultIsStmt);
574void DWARFDebugLine::ParsingState::appendRowToMatrix() {
575 unsigned RowNumber = LineTable->Rows.size();
576 if (Sequence.Empty) {
578 Sequence.Empty =
false;
579 Sequence.LowPC = Row.Address.Address;
580 Sequence.FirstRowIndex = RowNumber;
582 LineTable->appendRow(Row);
583 if (Row.EndSequence) {
585 Sequence.HighPC = Row.Address.Address;
586 Sequence.LastRowIndex = RowNumber + 1;
587 Sequence.SectionIndex = Row.Address.SectionIndex;
589 LineTable->appendSequence(Sequence);
597 LineTableConstIter Pos = LineTableMap.find(
Offset);
598 if (Pos != LineTableMap.end())
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)
975 case DW_LNE_define_file:
1006 *
OS <<
" (" <<
Name <<
", dir=" << FileEntry.
DirIdx <<
", mod_time="
1008 <<
", length=" << FileEntry.
Length <<
")";
1012 case DW_LNE_set_discriminator:
1013 State.Row.Discriminator = TableData.
getULEB128(Cursor);
1015 *
OS <<
" (" << State.Row.Discriminator <<
")";
1020 *
OS <<
format(
"Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
1021 <<
format(
" length %" PRIx64, Len);
1024 TableData.
skip(Cursor, Len - 1);
1032 if (Cursor && Cursor.
tell() !=
End)
1035 "unexpected line op length at offset 0x%8.8" PRIx64
1036 " expected 0x%2.2" PRIx64
" found 0x%2.2" PRIx64,
1037 ExtOffset, Len, Cursor.
tell() - ExtOffset));
1040 uint8_t Byte = TableData.
getU8(ByteCursor);
1042 *
OS <<
" (<parsing error>";
1044 *
OS <<
format(
" %2.2" PRIx8, Byte);
1045 Byte = TableData.
getU8(ByteCursor);
1046 }
while (ByteCursor);
1067 case DW_LNS_advance_pc:
1071 if (std::optional<uint64_t> Operand =
1072 parseULEB128<uint64_t>(TableData, Cursor)) {
1074 State.advanceAddrOpIndex(*Operand, Opcode, OpcodeOffset);
1081 case DW_LNS_advance_line:
1085 int64_t LineDelta = TableData.
getSLEB128(Cursor);
1087 State.Row.Line += LineDelta;
1089 *
OS <<
" (" << State.Row.Line <<
")";
1094 case DW_LNS_set_file:
1097 if (std::optional<uint16_t> File =
1098 parseULEB128<uint16_t>(TableData, Cursor)) {
1099 State.Row.File = *File;
1101 *
OS <<
" (" << State.Row.File <<
")";
1105 case DW_LNS_set_column:
1108 if (std::optional<uint16_t> Column =
1109 parseULEB128<uint16_t>(TableData, Cursor)) {
1110 State.Row.Column = *Column;
1112 *
OS <<
" (" << State.Row.Column <<
")";
1116 case DW_LNS_negate_stmt:
1119 State.Row.IsStmt = !State.Row.IsStmt;
1122 case DW_LNS_set_basic_block:
1125 State.Row.BasicBlock =
true;
1128 case DW_LNS_const_add_pc:
1142 State.advanceForOpcode(Opcode, OpcodeOffset);
1144 *
OS <<
format(
" (addr += 0x%16.16" PRIx64
", op-index += %" PRIu8
1150 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();
1321 if (Result != UnknownRowIndex ||
1327 return lookupAddressImpl(
Address);
1330uint32_t DWARFDebugLine::LineTable::lookupAddressImpl(
1338 if (It == Sequences.end() || It->SectionIndex !=
Address.SectionIndex)
1339 return UnknownRowIndex;
1340 return findRowInSeq(*It,
Address);
1345 std::vector<uint32_t> &Result)
const {
1348 if (lookupAddressRangeImpl(
Address,
Size, Result))
1356 return lookupAddressRangeImpl(
Address,
Size, Result);
1359bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
1361 std::vector<uint32_t> &Result)
const {
1362 if (Sequences.empty())
1369 SequenceIter LastSeq = Sequences.end();
1372 if (SeqPos == LastSeq || !SeqPos->containsPC(
Address))
1375 SequenceIter StartPos = SeqPos;
1380 while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
1385 if (SeqPos == StartPos)
1386 FirstRowIndex = findRowInSeq(CurSeq,
Address);
1390 findRowInSeq(CurSeq, {EndAddr - 1,
Address.SectionIndex});
1391 if (LastRowIndex == UnknownRowIndex)
1394 assert(FirstRowIndex != UnknownRowIndex);
1395 assert(LastRowIndex != UnknownRowIndex);
1397 for (
uint32_t I = FirstRowIndex;
I <= LastRowIndex; ++
I) {
1398 Result.push_back(
I);
1407std::optional<StringRef>
1408DWARFDebugLine::LineTable::getSourceByIndex(
uint64_t FileIndex,
1410 if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex))
1411 return std::nullopt;
1412 const FileNameEntry &Entry = Prologue.getFileNameEntry(FileIndex);
1415 return std::nullopt;
1429 if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
1436 if (Kind == FileLineInfoKind::RawValue ||
1438 Result = std::string(FileName);
1441 if (Kind == FileLineInfoKind::BaseNameOnly) {
1449 if (getVersion() >= 5) {
1452 if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) &&
1453 Entry.DirIdx < IncludeDirectories.size())
1456 if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size())
1464 if (Kind == FileLineInfoKind::AbsoluteFilePath &&
1465 (getVersion() < 5 || Entry.DirIdx != 0) && !CompDir.
empty() &&
1469 assert((Kind == FileLineInfoKind::AbsoluteFilePath ||
1470 Kind == FileLineInfoKind::RelativeFilePath) &&
1471 "invalid FileLineInfo Kind");
1475 Result = std::string(FilePath);
1484 if (RowIndex == -1U)
1487 const auto &
Row = Rows[RowIndex];
1488 if (!getFileNameByIndex(
Row.
File, CompDir, Kind, Result.FileName))
1493 Result.Source = getSourceByIndex(
Row.
File, Kind);
1522 for (
const auto &U : Units)
1523 if (
auto CUDIE = U->getUnitDIE())
1525 LineToUnit.insert(std::make_pair(*StmtOffset, &*U));
1539 return TotalLength != 0u;
1547 "parsing should have terminated");
1553 UnrecoverableErrorHandler(std::move(Err));
1554 moveToNextTable(OldOffset, LT.Prologue);
1562 "parsing should have terminated");
1566 if (
Error Err = LT.Prologue.parse(DebugLineData, &
Offset,
1567 RecoverableErrorHandler,
Context, U))
1568 UnrecoverableErrorHandler(std::move(Err));
1569 moveToNextTable(OldOffset, LT.Prologue);
1574 auto It = LineToUnit.find(
Offset);
1575 if (It != LineToUnit.end())
1581bool DWARFDebugLine::SectionParser::hasValidVersion(
uint64_t Offset) {
1585 uint16_t Version = HeaderData.getU16(Cursor);
1596void DWARFDebugLine::SectionParser::moveToNextTable(
uint64_t OldOffset,
1597 const Prologue &
P) {
1601 if (!
P.totalLengthIsValid()) {
1606 Offset = OldOffset +
P.TotalLength +
P.sizeofTotalLength();
1614 if (hasValidVersion(
Offset))
1620 for (
unsigned Align : {4, 8}) {
1629 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.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
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.
bool getDirectoryForEntry(const FileNameEntry &Entry, std::string &Directory) const
Extracts directory name by its Entry in include directories table in prologue.
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.
uint32_t lookupAddress(object::SectionedAddress Address) const
Returns the index of the row with file/line info for a given address, or UnknownRowIndex if there is ...
bool getFileLineInfoForAddress(object::SectionedAddress Address, const char *CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, DILineInfo &Result) const
Fills the Result argument with the file and line information corresponding to Address.
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