LLVM: lib/DebugInfo/DWARF/DWARFDebugLine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

21#include

22#include

23#include

24#include

25#include

26#include

27

28using namespace llvm;

29using namespace dwarf;

30

32

33namespace {

34

35struct ContentDescriptor {

38};

39

41

42}

43

45 return Version >= 2 && Version <= 5;

46}

47

50 switch (ContentType) {

51 case dwarf::DW_LNCT_timestamp:

53 break;

54 case dwarf::DW_LNCT_size:

56 break;

57 case dwarf::DW_LNCT_MD5:

59 break;

60 case dwarf::DW_LNCT_LLVM_source:

62 break;

63 default:

64

65

66 break;

67 }

68}

69

71

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();

79}

80

81std::optional<uint64_t>

84 return std::nullopt;

86 assert(DwarfVersion != 0 &&

87 "line table prologue has no dwarf version information");

88

89 if (DwarfVersion >= 5)

92}

93

97 assert(DwarfVersion != 0 &&

98 "line table prologue has no dwarf version information");

99

100 if (DwarfVersion >= 5)

103}

104

116

120 return;

122 OS << "Line table prologue:\n"

123 << format(" total_length: 0x%0*" PRIx64 "\n", OffsetDumpWidth,

128 return;

132 OS << format(" prologue_length: 0x%0*" PRIx64 "\n", OffsetDumpWidth,

140

142 OS << formatv("standard_opcode_lengths[{0}] = {1}\n",

145

147

150 OS << format("include_directories[%3u] = ", I + DirBase);

152 OS << '\n';

153 }

154 }

155

157

161 OS << format("file_names[%3u]:\n", I + FileBase);

162 OS << " name: ";

163 FileEntry.Name.dump(OS, DumpOptions);

164 OS << '\n' << format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);

166 OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';

168 OS << format(" mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);

170 OS << format(" length: 0x%8.8" PRIx64 "\n", FileEntry.Length);

173 if (!Source)

175 else if ((*Source)[0]) {

176 OS << " source: ";

177 FileEntry.Source.dump(OS, DumpOptions);

178 OS << '\n';

179 }

180 }

181 }

182 }

183}

184

185

190 std::vector &IncludeDirectories,

191 std::vectorDWARFDebugLine::FileNameEntry &FileNames) {

192 while (true) {

195 if (Err) {

198 "include directories table was not null "

199 "terminated before the end of the prologue");

200 }

202 break;

205 IncludeDirectories.push_back(Dir);

206 }

207

210

211 while (true) {

214 if (!Err && Name.empty())

215 break;

216

218 FileEntry.Name =

220 FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr, &Err);

222 FileEntry.Length = DebugLineData.getULEB128(OffsetPtr, &Err);

223

224 if (Err) {

228 "file names table was not null terminated before "

229 "the end of the prologue");

230 }

231 FileNames.push_back(FileEntry);

232 }

233

235}

236

237

238

239

240static llvm::Expected

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;

249 Descriptor.Type =

252 if (Descriptor.Type == dwarf::DW_LNCT_path)

253 HasPath = true;

254 if (ContentTypes)

256 Descriptors.push_back(Descriptor);

257 }

258

259 if (Err)

261 "failed to parse entry content descriptors: %s",

263

264 if (!HasPath)

266 "failed to parse entry content descriptions"

267 " because no path was found");

268 return Descriptors;

269}

270

276 std::vector &IncludeDirectories,

277 std::vectorDWARFDebugLine::FileNameEntry &FileNames) {

278

281 if (!DirDescriptors)

282 return DirDescriptors.takeError();

283

284

286 for (uint64_t I = 0; I != DirEntryCount; ++I) {

287 for (auto Descriptor : *DirDescriptors) {

289 switch (Descriptor.Type) {

290 case DW_LNCT_path:

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);

296 break;

297 default:

298 if (Value.skipValue(DebugLineData, OffsetPtr, FormParams))

300 "failed to parse directory entry because "

301 "skipping the form value failed");

302 }

303 }

304 }

305

306

309 if (!FileDescriptors)

310 return FileDescriptors.takeError();

311

312

314 for (uint64_t I = 0; I != FileEntryCount; ++I) {

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) {

323 case DW_LNCT_path:

325 break;

326 case DW_LNCT_LLVM_source:

328 break;

329 case DW_LNCT_directory_index:

330 FileEntry.DirIdx = *Value.getAsUnsignedConstant();

331 break;

332 case DW_LNCT_timestamp:

333 FileEntry.ModTime = *Value.getAsUnsignedConstant();

334 break;

335 case DW_LNCT_size:

336 FileEntry.Length = *Value.getAsUnsignedConstant();

337 break;

338 case DW_LNCT_MD5:

339 if (Value.getAsBlock() || Value.getAsBlock()->size() != 16)

342 "failed to parse file entry because the MD5 hash is invalid");

345 break;

346 default:

347 break;

348 }

349 }

350 FileNames.push_back(FileEntry);

351 }

353}

354

362

367 const uint64_t PrologueOffset = *OffsetPtr;

368

373

374 DebugLineData =

378

379

380

381 *OffsetPtr = Cursor.tell();

384 "parsing line table prologue at offset 0x%8.8" PRIx64

385 ": unsupported version %" PRIu16,

387 }

388

393 if (Cursor) {

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));

401 }

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));

408 }

409 }

411 }

412

416 DebugLineData = DWARFDataExtractor(DebugLineData, EndPrologueOffset);

424

426

427

428

431 "parsing line table prologue at offset 0x%8.8" PRIx64

432 " found opcode base of 0. Assuming no standard opcodes",

433 PrologueOffset));

434 } else if (Cursor) {

439 }

440 }

441

442 *OffsetPtr = Cursor.tell();

443

444

445

446 if (!Cursor)

449 "parsing line table prologue at offset 0x%8.8" PRIx64 ": %s",

450 PrologueOffset, toString(Cursor.takeError()).c_str());

451

458 if (E) {

462 "parsing line table prologue at 0x%8.8" PRIx64

463 " found an invalid directory or file table description at"

464 " 0x%8.8" PRIx64,

465 PrologueOffset, *OffsetPtr),

466 std::move(E)));

468 }

469

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));

478 }

480}

481

483

490

499 IsStmt = DefaultIsStmt;

505}

506

509 << "Address Line Column File ISA Discriminator OpIndex "

510 "Flags\n";

512 << "------------------ ------ ------ ------ --- ------------- ------- "

513 "-------------\n";

514}

515

524

526

536

538

541 Prologue.dump(OS, DumpOptions);

542

543 if (Rows.empty()) {

544 OS << '\n';

546 for (const Row &R : Rows) {

547 R.dump(OS);

548 }

549 }

550

551

552

553 OS << '\n';

554}

555

561

562DWARFDebugLine::ParsingState::ParsingState(

566

567void DWARFDebugLine::ParsingState::resetRowAndSequence(uint64_t Offset) {

568 Row.reset(LineTable->Prologue.DefaultIsStmt);

569 Sequence.reset();

570 Sequence.StmtSeqOffset = Offset;

571}

572

573void DWARFDebugLine::ParsingState::appendRowToMatrix() {

574 unsigned RowNumber = LineTable->Rows.size();

575 if (Sequence.Empty) {

576

577 Sequence.Empty = false;

578 Sequence.LowPC = Row.Address.Address;

579 Sequence.FirstRowIndex = RowNumber;

580 }

583

590 }

592}

593

594const DWARFDebugLine::LineTable *

596 LineTableConstIter Pos = LineTableMap.find(Offset);

597 if (Pos != LineTableMap.end())

598 return &Pos->second;

599 return nullptr;

600}

601

607 "offset 0x%8.8" PRIx64

608 " is not a valid debug line section offset",

610

611 std::pair<LineTableIter, bool> Pos =

612 LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));

613 LineTable *LT = &Pos.first->second;

614 if (Pos.second) {

616 LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorHandler))

617 return std::move(Err);

618 return LT;

619 }

620 return LT;

621}

622

624 LineTableMap.erase(Offset);

625}

626

629 if (Opcode < OpcodeBase)

631 return "special";

632}

633

634DWARFDebugLine::ParsingState::AddrOpIndexDelta

635DWARFDebugLine::ParsingState::advanceAddrOpIndex(uint64_t OperationAdvance,

636 uint8_t Opcode,

637 uint64_t OpcodeOffset) {

639

640

641

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));

651

652

653

654

655

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 "

663 "may be incorrect",

664 LineTableOffset, OpcodeName.data(), OpcodeOffset,

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;

675

676

677

678

679

680

681

682

683

684

685

686

687 uint8_t MaxOpsPerInst =

689

690 uint64_t AddrOffset = ((Row.OpIndex + OperationAdvance) / MaxOpsPerInst) *

693

696 int16_t OpIndexDelta = static_cast<int16_t>(Row.OpIndex) - PrevOpIndex;

697

698 return {AddrOffset, OpIndexDelta};

699}

700

701DWARFDebugLine::ParsingState::OpcodeAdvanceResults

702DWARFDebugLine::ParsingState::advanceForOpcode(uint8_t Opcode,

703 uint64_t OpcodeOffset) {

704 assert(Opcode == DW_LNS_const_add_pc ||

707 StringRef OpcodeName =

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;

717 }

718

719 uint8_t OpcodeValue = Opcode;

720 if (Opcode == DW_LNS_const_add_pc)

721 OpcodeValue = 255;

723 uint64_t OperationAdvance =

726 : 0;

727 AddrOpIndexDelta Advance =

728 advanceAddrOpIndex(OperationAdvance, Opcode, OpcodeOffset);

729 return {Advance.AddrOffset, Advance.OpIndexDelta, AdjustedOpcode};

730}

731

732DWARFDebugLine::ParsingState::SpecialOpcodeDelta

733DWARFDebugLine::ParsingState::handleSpecialOpcode(uint8_t Opcode,

734 uint64_t OpcodeOffset) {

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766 DWARFDebugLine::ParsingState::OpcodeAdvanceResults AddrAdvanceResult =

767 advanceForOpcode(Opcode, OpcodeOffset);

768 int32_t LineOffset = 0;

770 LineOffset =

774 return {AddrAdvanceResult.AddrDelta, LineOffset,

776}

777

778

779

780template

784 if (Cursor)

786 return std::nullopt;

787}

788

794 assert((OS || Verbose) && "cannot have verbose output without stream");

795 const uint64_t DebugLineOffset = *OffsetPtr;

796

798

799 Error PrologueErr =

800 Prologue.parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U);

801

802 if (OS) {

805 Prologue.dump(*OS, DumpOptions);

806 }

807

808 if (PrologueErr) {

809

810

811 if (OS)

812 *OS << "\n";

813 return PrologueErr;

814 }

815

818 ProgramLength)) {

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));

828

829 ProgramLength = BytesRemaining;

830 }

831

832

833

834 const uint64_t EndOffset = DebugLineOffset + ProgramLength;

836

837

840 else

843

844 ParsingState State(this, DebugLineOffset, RecoverableErrorHandler);

845

846 *OffsetPtr = DebugLineOffset + Prologue.getLength();

847 if (OS && *OffsetPtr < EndOffset) {

848 *OS << '\n';

850 }

851

852

853 State.resetRowAndSequence(*OffsetPtr);

854

855 bool TombstonedAddress = false;

856 auto EmitRow = [&] {

857 if (!TombstonedAddress) {

859 *OS << "\n";

861 }

862 if (OS)

863 State.Row.dump(*OS);

864 State.appendRowToMatrix();

865 }

866 };

867 while (*OffsetPtr < EndOffset) {

869

871 *OS << format("0x%08.08" PRIx64 ": ", *OffsetPtr);

872

873 uint64_t OpcodeOffset = *OffsetPtr;

875 size_t RowCount = Rows.size();

876

878 *OS << format("%02.02" PRIx8 " ", Opcode);

879

880 if (Opcode == 0) {

881

882

884 uint64_t ExtOffset = Cursor.tell();

885

886

887 if (Len == 0) {

889 *OS << "Badly formed extended line op (length 0)\n";

890 if (!Cursor) {

892 *OS << "\n";

893 RecoverableErrorHandler(Cursor.takeError());

894 }

895 *OffsetPtr = Cursor.tell();

896 continue;

897 }

898

900

901

902 uint64_t OperandOffset = Cursor.tell();

905 switch (SubOpcode) {

906 case DW_LNE_end_sequence:

907

908

909

910

911

912

913

914 State.Row.EndSequence = true;

915

916

917

918 EmitRow();

919

920

921 State.resetRowAndSequence(Cursor.tell());

922 break;

923

924 case DW_LNE_set_address:

925

926

927

928

929

930

931

932

933

934

935 {

937 uint64_t OpcodeAddressSize = Len - 1;

938 if (ExtractorAddressSize != OpcodeAddressSize &&

939 ExtractorAddressSize != 0)

942 "mismatching address size at offset 0x%8.8" PRIx64

943 " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,

944 ExtOffset, ExtractorAddressSize, Len - 1));

945

946

947

948

949 if (OpcodeAddressSize != 1 && OpcodeAddressSize != 2 &&

950 OpcodeAddressSize != 4 && OpcodeAddressSize != 8) {

953 "address size 0x%2.2" PRIx64

954 " of DW_LNE_set_address opcode at offset 0x%8.8" PRIx64

955 " is unsupported",

956 OpcodeAddressSize, ExtOffset));

957 TableData.skip(Cursor, OpcodeAddressSize);

958 } else {

961 Cursor, &State.Row.Address.SectionIndex);

962 State.Row.OpIndex = 0;

963

966 TombstonedAddress = State.Row.Address.Address == Tombstone;

967

968

969 if (ExtractorAddressSize != 0)

971 }

972

974 *OS << " (";

976 State.Row.Address.Address);

977 *OS << ')';

978 }

979 }

980 break;

981

982 case DW_LNE_define_file:

983

984

985

986

987

988

989

990

991

992

993

994

995

996

997

998

999

1000

1001

1002

1003 {

1005 const char *Name = TableData.getCStr(Cursor);

1006 FileEntry.Name =

1011 Prologue.FileNames.push_back(FileEntry);

1013 *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="

1014 << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)

1015 << ", length=" << FileEntry.Length << ")";

1016 }

1017 break;

1018

1019 case DW_LNE_set_discriminator:

1020 State.Row.Discriminator = TableData.getULEB128(Cursor);

1022 *OS << " (" << State.Row.Discriminator << ")";

1023 break;

1024

1025 default:

1027 *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)

1028 << format(" length %" PRIx64, Len);

1029

1030

1031 TableData.skip(Cursor, Len - 1);

1032 break;

1033 }

1034

1035

1036

1037

1038 uint64_t End = ExtOffset + Len;

1039 if (Cursor && Cursor.tell() != End)

1042 "unexpected line op length at offset 0x%8.8" PRIx64

1043 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64,

1044 ExtOffset, Len, Cursor.tell() - ExtOffset));

1045 if (!Cursor && Verbose) {

1048 if (ByteCursor) {

1049 *OS << " (";

1050 do {

1051 *OS << format(" %2.2" PRIx8, Byte);

1052 Byte = TableData.getU8(ByteCursor);

1053 } while (ByteCursor);

1054 *OS << ")";

1055 }

1056

1057

1058

1059

1061 }

1062 *OffsetPtr = End;

1063 } else if (Opcode < Prologue.OpcodeBase) {

1066 switch (Opcode) {

1067

1068 case DW_LNS_copy:

1069

1070

1071 EmitRow();

1072 break;

1073

1074 case DW_LNS_advance_pc:

1075

1076

1077

1078 if (std::optional<uint64_t> Operand =

1081 State.advanceAddrOpIndex(*Operand, Opcode, OpcodeOffset);

1083 *OS << " (addr += " << Advance.AddrOffset

1084 << ", op-index += " << Advance.OpIndexDelta << ")";

1085 }

1086 break;

1087

1088 case DW_LNS_advance_line:

1089

1090

1091 {

1092 int64_t LineDelta = TableData.getSLEB128(Cursor);

1093 if (Cursor) {

1094 State.Row.Line += LineDelta;

1096 *OS << " (" << State.Row.Line << ")";

1097 }

1098 }

1099 break;

1100

1101 case DW_LNS_set_file:

1102

1103

1104 if (std::optional<uint16_t> File =

1106 State.Row.File = *File;

1108 *OS << " (" << State.Row.File << ")";

1109 }

1110 break;

1111

1112 case DW_LNS_set_column:

1113

1114

1115 if (std::optional<uint16_t> Column =

1117 State.Row.Column = *Column;

1119 *OS << " (" << State.Row.Column << ")";

1120 }

1121 break;

1122

1123 case DW_LNS_negate_stmt:

1124

1125

1126 State.Row.IsStmt = !State.Row.IsStmt;

1127 break;

1128

1129 case DW_LNS_set_basic_block:

1130

1131

1132 State.Row.BasicBlock = true;

1133 break;

1134

1135 case DW_LNS_const_add_pc:

1136

1137

1138

1139

1140

1141

1142

1143

1144

1145

1146

1147 {

1149 State.advanceForOpcode(Opcode, OpcodeOffset);

1151 *OS << format(" (addr += 0x%16.16" PRIx64 ", op-index += %" PRIu8

1152 ")",

1154 }

1155 break;

1156

1157 case DW_LNS_fixed_advance_pc:

1158

1159

1160

1161

1162

1163

1164

1165

1166

1167

1168 {

1170 if (Cursor) {

1171 State.Row.Address.Address += PCOffset;

1172 State.Row.OpIndex = 0;

1174 *OS << format(" (addr += 0x%4.4" PRIx16 ", op-index = 0)",

1175 PCOffset);

1176 }

1177 }

1178 break;

1179

1180 case DW_LNS_set_prologue_end:

1181

1182

1183 State.Row.PrologueEnd = true;

1184 break;

1185

1186 case DW_LNS_set_epilogue_begin:

1187

1188

1189 State.Row.EpilogueBegin = true;

1190 break;

1191

1192 case DW_LNS_set_isa:

1193

1194

1195 if (std::optional<uint8_t> Isa =

1197 State.Row.Isa = *Isa;

1199 *OS << " (" << (uint64_t)State.Row.Isa << ")";

1200 }

1201 break;

1202

1203 default:

1204

1205

1206

1207 {

1208 assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());

1210 *OS << "Unrecognized standard opcode";

1211 uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];

1212 std::vector<uint64_t> Operands;

1213 for (uint8_t I = 0; I < OpcodeLength; ++I) {

1214 if (std::optional<uint64_t> Value =

1216 Operands.push_back(*Value);

1217 else

1218 break;

1219 }

1220 if (Verbose && !Operands.empty()) {

1221 *OS << " (operands: ";

1222 bool First = true;

1225 *OS << ", ";

1227 *OS << format("0x%16.16" PRIx64, Value);

1228 }

1230 *OS << ')';

1231 }

1232 }

1233 break;

1234 }

1235

1236 *OffsetPtr = Cursor.tell();

1237 } else {

1238

1240 State.handleSpecialOpcode(Opcode, OpcodeOffset);

1241

1243 *OS << "address += " << Delta.Address << ", line += " << Delta.Line

1244 << ", op-index += " << Delta.OpIndex;

1245 EmitRow();

1246 *OffsetPtr = Cursor.tell();

1247 }

1248

1249

1250

1252 *OS << "\n";

1253

1254

1255

1256

1257

1258 if (!Cursor && Opcode != 0) {

1260 *OS << "\n";

1261 return Cursor.takeError();

1262 }

1263

1264 if (!Cursor)

1265 RecoverableErrorHandler(Cursor.takeError());

1266 }

1267

1268 if (!State.Sequence.Empty)

1271 "last sequence in debug line table at offset 0x%8.8" PRIx64

1272 " is not terminated",

1273 DebugLineOffset));

1274

1275

1278

1279

1280

1281

1282

1283

1284

1285 }

1286

1287

1288

1289 if (OS)

1290 *OS << "\n";

1291

1293}

1294

1295uint32_t DWARFDebugLine::LineTable::findRowInSeq(

1299 return UnknownRowIndex;

1301

1302

1303

1304

1305

1306

1307

1308

1311 RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;

1312 RowIter LastRow = Rows.begin() + Seq.LastRowIndex;

1315 RowIter RowPos = std::upper_bound(FirstRow + 1, LastRow - 1, Row,

1317 1;

1319 return RowPos - Rows.begin();

1320}

1321

1324 bool *IsApproximateLine) const {

1325

1326

1327 uint32_t Result = lookupAddressImpl(Address, IsApproximateLine);

1328

1331 return Result;

1332

1333

1335 return lookupAddressImpl(Address, IsApproximateLine);

1336}

1337

1340 bool *IsApproximateLine) const {

1341 assert((!IsApproximateLine || !*IsApproximateLine) &&

1342 "Make sure IsApproximateLine is appropriately "

1343 "initialized, if provided");

1344

1350 if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex)

1351 return UnknownRowIndex;

1352

1354 if (RowIndex == UnknownRowIndex || !IsApproximateLine)

1355 return RowIndex;

1356

1357

1358 uint32_t ApproxRowIndex = RowIndex;

1359

1360 for (; ApproxRowIndex >= It->FirstRowIndex; --ApproxRowIndex) {

1361 if (Rows[ApproxRowIndex].Line)

1362 return ApproxRowIndex;

1363 *IsApproximateLine = true;

1364 }

1365

1366 if (ApproxRowIndex < It->FirstRowIndex)

1367 *IsApproximateLine = false;

1368

1369 return RowIndex;

1370}

1371

1374 std::vector<uint32_t> &Result,

1375 std::optional<uint64_t> StmtSequenceOffset) const {

1376

1377

1378 if (lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset))

1379 return true;

1380

1382 return false;

1383

1384

1386 return lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset);

1387}

1388

1389bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(

1391 std::vector<uint32_t> &Result,

1392 std::optional<uint64_t> StmtSequenceOffset) const {

1393 if (Sequences.empty())

1394 return false;

1396

1400 SequenceIter LastSeq = Sequences.end();

1401 SequenceIter SeqPos;

1402

1403 if (StmtSequenceOffset) {

1404

1405

1406 SeqPos = std::find_if(Sequences.begin(), LastSeq,

1408 return S.StmtSeqOffset == *StmtSequenceOffset;

1409 });

1410

1411

1412 if (SeqPos == LastSeq)

1413 return false;

1414

1415

1416

1417 LastSeq = SeqPos + 1;

1418 } else {

1419

1420 SeqPos = std::upper_bound(Sequences.begin(), LastSeq, Sequence,

1422 if (SeqPos == LastSeq)

1423 return false;

1424 }

1425

1426

1427 if (!SeqPos->containsPC(Address))

1428 return false;

1429

1430 SequenceIter StartPos = SeqPos;

1431

1432

1433 while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {

1435

1436

1438 if (SeqPos == StartPos)

1439 FirstRowIndex = findRowInSeq(CurSeq, Address);

1440

1441

1443 findRowInSeq(CurSeq, {EndAddr - 1, Address.SectionIndex});

1444 if (LastRowIndex == UnknownRowIndex)

1446

1447 assert(FirstRowIndex != UnknownRowIndex);

1448 assert(LastRowIndex != UnknownRowIndex);

1449

1450 for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {

1452 }

1453

1454 ++SeqPos;

1455 }

1456

1457 return true;

1458}

1459

1460std::optional

1461DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,

1462 FileLineInfoKind Kind) const {

1464 return std::nullopt;

1467 return StringRef(*E);

1468 return std::nullopt;

1469}

1470

1478

1482 if (Kind == FileLineInfoKind::None || hasFileAtIndex(FileIndex))

1483 return false;

1486 if (!E)

1487 return false;

1489 if (Kind == FileLineInfoKind::RawValue ||

1491 Result = std::string(FileName);

1492 return true;

1493 }

1494 if (Kind == FileLineInfoKind::BaseNameOnly) {

1496 return true;

1497 }

1498

1501

1503

1504

1505 if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) &&

1508 } else {

1511 }

1512

1513

1514

1515

1516

1517 if (Kind == FileLineInfoKind::AbsoluteFilePath &&

1518 (getVersion() < 5 || Entry.DirIdx != 0) && !CompDir.empty() &&

1521

1522 assert((Kind == FileLineInfoKind::AbsoluteFilePath ||

1523 Kind == FileLineInfoKind::RelativeFilePath) &&

1524 "invalid FileLineInfo Kind");

1525

1526

1528 Result = std::string(FilePath);

1529 return true;

1530}

1531

1534 FileLineInfoKind Kind, DILineInfo &Result) const {

1535

1538 if (RowIndex == -1U)

1539 return false;

1540

1541 const auto &Row = Rows[RowIndex];

1543 return false;

1547 Result.Source = getSourceByIndex(Row.File, Kind);

1548 return true;

1549}

1550

1552 const FileNameEntry &Entry, std::string &Directory) const {

1553 if (Prologue.getVersion() >= 5) {

1554 if (Entry.DirIdx < Prologue.IncludeDirectories.size()) {

1555 Directory =

1557 return true;

1558 }

1559 return false;

1560 }

1561 if (0 < Entry.DirIdx && Entry.DirIdx <= Prologue.IncludeDirectories.size()) {

1562 Directory =

1564 return true;

1565 }

1566 return false;

1567}

1568

1569

1570

1571

1572

1576 for (const auto &U : Units)

1577 if (auto CUDIE = U->getUnitDIE())

1578 if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))

1579 LineToUnit.insert(std::make_pair(*StmtOffset, &*U));

1580 return LineToUnit;

1581}

1582

1586 : DebugLineData(Data), Context(C) {

1588 if (!DebugLineData.isValidOffset(Offset))

1589 Done = true;

1590}

1591

1595

1600 assert(DebugLineData.isValidOffset(Offset) &&

1601 "parsing should have terminated");

1602 DWARFUnit *U = prepareToParse(Offset);

1603 uint64_t OldOffset = Offset;

1605 if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,

1606 RecoverableErrorHandler, OS, Verbose))

1607 UnrecoverableErrorHandler(std::move(Err));

1608 moveToNextTable(OldOffset, LT.Prologue);

1609 return LT;

1610}

1611

1615 assert(DebugLineData.isValidOffset(Offset) &&

1616 "parsing should have terminated");

1617 DWARFUnit *U = prepareToParse(Offset);

1618 uint64_t OldOffset = Offset;

1620 if (Error Err = LT.Prologue.parse(DebugLineData, &Offset,

1621 RecoverableErrorHandler, Context, U))

1622 UnrecoverableErrorHandler(std::move(Err));

1623 moveToNextTable(OldOffset, LT.Prologue);

1624}

1625

1628 auto It = LineToUnit.find(Offset);

1629 if (It != LineToUnit.end())

1630 U = It->second;

1631 DebugLineData.setAddressSize(U ? U->getAddressByteSize() : 0);

1632 return U;

1633}

1634

1635bool DWARFDebugLine::SectionParser::hasValidVersion(uint64_t Offset) {

1638 DWARFDataExtractor HeaderData(DebugLineData, Cursor.tell() + TotalLength);

1640 if (!Cursor) {

1641

1642

1643

1645 return false;

1646 }

1648}

1649

1650void DWARFDebugLine::SectionParser::moveToNextTable(uint64_t OldOffset,

1652

1653

1654

1655 if (P.totalLengthIsValid()) {

1656 Done = true;

1657 return;

1658 }

1659

1660 Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();

1662 Done = true;

1663 return;

1664 }

1665

1666

1667

1668 if (hasValidVersion(Offset))

1669 return;

1670

1671

1672

1673

1674 for (unsigned Align : {4, 8}) {

1675 uint64_t AlignedOffset = alignTo(Offset, Align);

1676 if (!DebugLineData.isValidOffset(AlignedOffset)) {

1677

1678

1679

1680 Done = true;

1681 return;

1682 }

1683 if (hasValidVersion(AlignedOffset)) {

1684 Offset = AlignedOffset;

1685 break;

1686 }

1687 }

1688}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

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)

Definition DWARFDebugLine.cpp:272

static Error parseV2DirFileTables(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, DWARFDebugLine::ContentTypeTracker &ContentTypes, std::vector< DWARFFormValue > &IncludeDirectories, std::vector< DWARFDebugLine::FileNameEntry > &FileNames)

Definition DWARFDebugLine.cpp:187

static llvm::Expected< ContentDescriptors > parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr, DWARFDebugLine::ContentTypeTracker *ContentTypes)

Definition DWARFDebugLine.cpp:241

static DWARFDebugLine::SectionParser::LineToUnitMap buildLineToUnitMap(DWARFUnitVector::iterator_range Units)

Definition DWARFDebugLine.cpp:1574

static bool versionIsSupported(uint16_t Version)

Definition DWARFDebugLine.cpp:44

static StringRef getOpcodeName(uint8_t Opcode, uint8_t OpcodeBase)

Definition DWARFDebugLine.cpp:627

static std::optional< T > parseULEB128(DWARFDataExtractor &Data, DataExtractor::Cursor &Cursor)

Parse a ULEB128 using the specified Cursor.

Definition DWARFDebugLine.cpp:781

This file contains constants used for implementing Dwarf debug support.

static fatal_error_handler_t ErrorHandler

This file defines the SmallString class.

This file defines the SmallVector class.

LocallyHashedType DenseMapInfo< LocallyHashedType >::Tombstone

DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...

LLVM_ABI 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.

Definition DWARFDebugLine.cpp:1612

std::map< uint64_t, DWARFUnit * > LineToUnitMap

LLVM_ABI 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.

Definition DWARFDebugLine.cpp:1596

LLVM_ABI SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, DWARFUnitVector::iterator_range Units)

Definition DWARFDebugLine.cpp:1583

LLVM_ABI void clearLineTable(uint64_t Offset)

Definition DWARFDebugLine.cpp:623

LLVM_ABI Expected< const LineTable * > getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx, const DWARFUnit *U, function_ref< void(Error)> RecoverableErrorHandler)

Definition DWARFDebugLine.cpp:602

LLVM_ABI const LineTable * getLineTable(uint64_t Offset) const

Definition DWARFDebugLine.cpp:595

static LLVM_ABI DWARFFormValue createFromPValue(dwarf::Form F, const char *V)

LLVM_ABI void dumpAddress(raw_ostream &OS, uint64_t Address) const

LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOpts=DIDumpOptions()) const

LLVM_ABI Expected< const char * > getAsCString() const

llvm::iterator_range< UnitVector::iterator > iterator_range

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...

LLVM Value Representation.

An efficient, type-erasing, non-owning reference to a callable.

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.

LLVM_ABI StringRef LNExtendedString(unsigned Encoding)

LLVM_ABI StringRef FormatString(DwarfFormat Format)

LLVM_ABI StringRef LNStandardString(unsigned Standard)

@ C

The default llvm calling convention, compatible with C.

bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path)

Calculates the starting offsets for various sections within the .debug_names section.

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)

LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get filename.

LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)

Is path absolute?

LLVM_ABI 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.

FunctionAddr VTableAddr Value

void stable_sort(R &&Range)

SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)

auto uninitialized_copy(R &&Src, IterTy Dst)

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.

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

FunctionAddr VTableAddr uintptr_t uintptr_t Version

Error joinErrors(Error E1, Error E2)

Concatenate errors.

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.

FunctionAddr VTableAddr uintptr_t uintptr_t Data

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)

void consumeError(Error Err)

Consume a Error without doing anything.

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.

LLVM_ABI void trackContentType(dwarf::LineNumberEntryFormat ContentType)

Update tracked content types with ContentType.

Definition DWARFDebugLine.cpp:48

LLVM_ABI 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 ...

Definition DWARFDebugLine.cpp:1323

LLVM_ABI bool getDirectoryForEntry(const FileNameEntry &Entry, std::string &Directory) const

Extracts directory name by its Entry in include directories table in prologue.

Definition DWARFDebugLine.cpp:1551

const uint32_t UnknownRowIndex

Represents an invalid row.

LLVM_ABI 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.

Definition DWARFDebugLine.cpp:1532

LLVM_ABI 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.

Definition DWARFDebugLine.cpp:789

LLVM_ABI void clear()

Definition DWARFDebugLine.cpp:556

bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result) const

Extracts filename by its index in filename table in prologue.

LLVM_ABI LineTable()

Definition DWARFDebugLine.cpp:537

void appendSequence(const DWARFDebugLine::Sequence &S)

LLVM_ABI bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size, std::vector< uint32_t > &Result, std::optional< uint64_t > StmtSequenceOffset=std::nullopt) const

Fills the Result argument with the indices of the rows that correspond to the address range specified...

Definition DWARFDebugLine.cpp:1372

void appendRow(const DWARFDebugLine::Row &R)

LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const

Definition DWARFDebugLine.cpp:539

uint8_t MaxOpsPerInst

The maximum number of individual operations that may be encoded in an instruction.

uint8_t MinInstLength

The size in bytes of the smallest target machine instruction.

LLVM_ABI bool hasFileAtIndex(uint64_t FileIndex) const

Definition DWARFDebugLine.cpp:72

uint64_t PrologueLength

The number of bytes following the prologue_length field to the beginning of the first byte of the sta...

LLVM_ABI void clear()

Definition DWARFDebugLine.cpp:105

LLVM_ABI void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const

Definition DWARFDebugLine.cpp:117

uint32_t sizeofTotalLength() const

uint8_t SegSelectorSize

In v5, size in bytes of a segment selector.

uint16_t getVersion() const

int8_t LineBase

This parameter affects the meaning of the special opcodes. See below.

LLVM_ABI std::optional< uint64_t > getLastValidFileIndex() const

Definition DWARFDebugLine.cpp:82

uint32_t sizeofPrologueLength() const

LLVM_ABI Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr, function_ref< void(Error)> RecoverableErrorHandler, const DWARFContext &Ctx, const DWARFUnit *U=nullptr)

Definition DWARFDebugLine.cpp:363

uint8_t LineRange

This parameter affects the meaning of the special opcodes. See below.

LLVM_ABI Prologue()

Definition DWARFDebugLine.cpp:70

std::vector< DWARFFormValue > IncludeDirectories

uint8_t OpcodeBase

The number assigned to the first special opcode.

std::vector< uint8_t > StandardOpcodeLengths

LLVM_ABI bool totalLengthIsValid() const

Definition DWARFDebugLine.cpp:1592

uint8_t getAddressSize() const

LLVM_ABI const llvm::DWARFDebugLine::FileNameEntry & getFileNameEntry(uint64_t Index) const

Get DWARF-version aware access to the file name entry at the provided index.

Definition DWARFDebugLine.cpp:95

LLVM_ABI bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, std::string &Result, sys::path::Style Style=sys::path::Style::native) const

Definition DWARFDebugLine.cpp:1479

uint8_t DefaultIsStmt

The initial value of theis_stmtregister.

uint64_t TotalLength

The size in bytes of the statement information for this compilation unit (not including the total_len...

dwarf::FormParams FormParams

Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...

LLVM_ABI uint64_t getLength() const

Length of the prologue in bytes.

Definition DWARFDebugLine.cpp:355

ContentTypeTracker ContentTypes

This tracks which optional file format content types are present.

std::vector< FileNameEntry > FileNames

Standard .debug_line state machine structure.

uint8_t BasicBlock

A boolean indicating that the current instruction is the beginning of a basic block.

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.

uint8_t EpilogueBegin

A boolean indicating that the current address is one (of possibly many) where execution should be sus...

object::SectionedAddress Address

The program-counter value corresponding to a machine instruction generated by the compiler and sectio...

LLVM_ABI void postAppend()

Called after a row is appended to the matrix.

Definition DWARFDebugLine.cpp:484

uint8_t PrologueEnd

A boolean indicating that the current address is one (of possibly many) where execution should be sus...

uint16_t Column

An unsigned integer indicating a column number within a source line.

uint8_t EndSequence

A boolean indicating that the current address is that of the first byte after the end of a sequence o...

static LLVM_ABI void dumpTableHeader(raw_ostream &OS, unsigned Indent)

Definition DWARFDebugLine.cpp:507

uint8_t IsStmt

A boolean indicating that the current instruction is the beginning of a statement.

LLVM_ABI void reset(bool DefaultIsStmt)

Definition DWARFDebugLine.cpp:491

LLVM_ABI Row(bool DefaultIsStmt=false)

Definition DWARFDebugLine.cpp:482

uint8_t Isa

An unsigned integer whose value encodes the applicable instruction set architecture for the current i...

LLVM_ABI void dump(raw_ostream &OS) const

Definition DWARFDebugLine.cpp:516

uint8_t OpIndex

An unsigned integer representing the index of an operation within a VLIW instruction.

Represents a series of contiguous machine instructions.

uint64_t LowPC

Sequence describes instructions at address range [LowPC, HighPC) and is described by line table rows ...

static bool orderByHighPC(const Sequence &LHS, const Sequence &RHS)

LLVM_ABI void reset()

Definition DWARFDebugLine.cpp:527

LLVM_ABI Sequence()

Definition DWARFDebugLine.cpp:525

bool containsPC(object::SectionedAddress PC) const

uint64_t StmtSeqOffset

The offset into the line table where this sequence begins.

uint64_t SectionIndex

If relocation information is present then this is the index of the section which contains above addre...

LLVM_ABI SmallString< 32 > digest() const

A helper struct providing information about the byte size of DW_FORM values that vary in size dependi...

static const uint64_t UndefSection