1//===- DWARFDebugLine.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/ADT/SmallVector.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/BinaryFormat/Dwarf.h"
14#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
15#include "llvm/DebugInfo/DWARF/DWARFDie.h"
16#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
17#include "llvm/Support/Errc.h"
18#include "llvm/Support/Format.h"
19#include "llvm/Support/FormatVariadic.h"
20#include "llvm/Support/raw_ostream.h"
21#include <algorithm>
22#include <cassert>
23#include <cinttypes>
24#include <cstdint>
25#include <cstdio>
26#include <utility>
27
28using namespace llvm;
29using namespace dwarf;
30
31using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
32
33namespace {
34
35struct ContentDescriptor {
36 dwarf::LineNumberEntryFormat Type;
37 dwarf::Form Form;
38};
39
40using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
41
42} // end anonymous namespace
43
44static bool versionIsSupported(uint16_t Version) {
45 return Version >= 2 && Version <= 5;
46}
47
48void DWARFDebugLine::ContentTypeTracker::trackContentType(
49 dwarf::LineNumberEntryFormat ContentType) {
50 switch (ContentType) {
51 case dwarf::DW_LNCT_timestamp:
52 HasModTime = true;
53 break;
54 case dwarf::DW_LNCT_size:
55 HasLength = true;
56 break;
57 case dwarf::DW_LNCT_MD5:
58 HasMD5 = true;
59 break;
60 case dwarf::DW_LNCT_LLVM_source:
61 HasSource = true;
62 break;
63 default:
64 // We only care about values we consider optional, and new values may be
65 // added in the vendor extension range, so we do not match exhaustively.
66 break;
67 }
68}
69
70DWARFDebugLine::Prologue::Prologue() { clear(); }
71
72bool DWARFDebugLine::Prologue::hasFileAtIndex(uint64_t FileIndex) const {
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();
79}
80
81std::optional<uint64_t>
82DWARFDebugLine::Prologue::getLastValidFileIndex() const {
83 if (FileNames.empty())
84 return std::nullopt;
85 uint16_t DwarfVersion = getVersion();
86 assert(DwarfVersion != 0 &&
87 "line table prologue has no dwarf version information");
88 // In DWARF v5 the file names are 0-indexed.
89 if (DwarfVersion >= 5)
90 return FileNames.size() - 1;
91 return FileNames.size();
92}
93
94const llvm::DWARFDebugLine::FileNameEntry &
95DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const {
96 uint16_t DwarfVersion = getVersion();
97 assert(DwarfVersion != 0 &&
98 "line table prologue has no dwarf version information");
99 // In DWARF v5 the file names are 0-indexed.
100 if (DwarfVersion >= 5)
101 return FileNames[Index];
102 return FileNames[Index - 1];
103}
104
105void DWARFDebugLine::Prologue::clear() {
106 TotalLength = PrologueLength = 0;
107 SegSelectorSize = 0;
108 MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
109 OpcodeBase = 0;
110 FormParams = dwarf::FormParams({.Version: 0, .AddrSize: 0, .Format: DWARF32});
111 ContentTypes = ContentTypeTracker();
112 StandardOpcodeLengths.clear();
113 IncludeDirectories.clear();
114 FileNames.clear();
115}
116
117void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
118 DIDumpOptions DumpOptions) const {
119 if (!totalLengthIsValid())
120 return;
121 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format: FormParams.Format);
122 OS << "Line table prologue:\n"
123 << format(Fmt: " total_length: 0x%0*" PRIx64 "\n", Vals: OffsetDumpWidth,
124 Vals: TotalLength)
125 << " format: " << dwarf::FormatString(Format: FormParams.Format) << "\n"
126 << format(Fmt: " version: %u\n", Vals: getVersion());
127 if (!versionIsSupported(Version: getVersion()))
128 return;
129 if (getVersion() >= 5)
130 OS << format(Fmt: " address_size: %u\n", Vals: getAddressSize())
131 << format(Fmt: " seg_select_size: %u\n", Vals: SegSelectorSize);
132 OS << format(Fmt: " prologue_length: 0x%0*" PRIx64 "\n", Vals: OffsetDumpWidth,
133 Vals: PrologueLength)
134 << format(Fmt: " min_inst_length: %u\n", Vals: MinInstLength)
135 << format(Fmt: getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", Vals: MaxOpsPerInst)
136 << format(Fmt: " default_is_stmt: %u\n", Vals: DefaultIsStmt)
137 << format(Fmt: " line_base: %i\n", Vals: LineBase)
138 << format(Fmt: " line_range: %u\n", Vals: LineRange)
139 << format(Fmt: " opcode_base: %u\n", Vals: OpcodeBase);
140
141 for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
142 OS << formatv(Fmt: "standard_opcode_lengths[{0}] = {1}\n",
143 Vals: static_cast<dwarf::LineNumberOps>(I + 1),
144 Vals: StandardOpcodeLengths[I]);
145
146 if (!IncludeDirectories.empty()) {
147 // DWARF v5 starts directory indexes at 0.
148 uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
149 for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {
150 OS << format(Fmt: "include_directories[%3u] = ", Vals: I + DirBase);
151 IncludeDirectories[I].dump(OS, DumpOpts: DumpOptions);
152 OS << '\n';
153 }
154 }
155
156 if (!FileNames.empty()) {
157 // DWARF v5 starts file indexes at 0.
158 uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
159 for (uint32_t I = 0; I != FileNames.size(); ++I) {
160 const FileNameEntry &FileEntry = FileNames[I];
161 OS << format(Fmt: "file_names[%3u]:\n", Vals: I + FileBase);
162 OS << " name: ";
163 FileEntry.Name.dump(OS, DumpOpts: DumpOptions);
164 OS << '\n' << format(Fmt: " dir_index: %" PRIu64 "\n", Vals: FileEntry.DirIdx);
165 if (ContentTypes.HasMD5)
166 OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
167 if (ContentTypes.HasModTime)
168 OS << format(Fmt: " mod_time: 0x%8.8" PRIx64 "\n", Vals: FileEntry.ModTime);
169 if (ContentTypes.HasLength)
170 OS << format(Fmt: " length: 0x%8.8" PRIx64 "\n", Vals: FileEntry.Length);
171 if (ContentTypes.HasSource) {
172 auto Source = FileEntry.Source.getAsCString();
173 if (!Source)
174 consumeError(Err: Source.takeError());
175 else if ((*Source)[0]) {
176 OS << " source: ";
177 FileEntry.Source.dump(OS, DumpOpts: DumpOptions);
178 OS << '\n';
179 }
180 }
181 }
182 }
183}
184
185// Parse v2-v4 directory and file tables.
186static Error
187parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
188 uint64_t *OffsetPtr,
189 DWARFDebugLine::ContentTypeTracker &ContentTypes,
190 std::vector<DWARFFormValue> &IncludeDirectories,
191 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
192 while (true) {
193 Error Err = Error::success();
194 StringRef S = DebugLineData.getCStrRef(OffsetPtr, Err: &Err);
195 if (Err) {
196 consumeError(Err: std::move(Err));
197 return createStringError(EC: errc::invalid_argument,
198 S: "include directories table was not null "
199 "terminated before the end of the prologue");
200 }
201 if (S.empty())
202 break;
203 DWARFFormValue Dir =
204 DWARFFormValue::createFromPValue(F: dwarf::DW_FORM_string, V: S.data());
205 IncludeDirectories.push_back(x: Dir);
206 }
207
208 ContentTypes.HasModTime = true;
209 ContentTypes.HasLength = true;
210
211 while (true) {
212 Error Err = Error::success();
213 StringRef Name = DebugLineData.getCStrRef(OffsetPtr, Err: &Err);
214 if (!Err && Name.empty())
215 break;
216
217 DWARFDebugLine::FileNameEntry FileEntry;
218 FileEntry.Name =
219 DWARFFormValue::createFromPValue(F: dwarf::DW_FORM_string, V: Name.data());
220 FileEntry.DirIdx = DebugLineData.getULEB128(offset_ptr: OffsetPtr, Err: &Err);
221 FileEntry.ModTime = DebugLineData.getULEB128(offset_ptr: OffsetPtr, Err: &Err);
222 FileEntry.Length = DebugLineData.getULEB128(offset_ptr: OffsetPtr, Err: &Err);
223
224 if (Err) {
225 consumeError(Err: std::move(Err));
226 return createStringError(
227 EC: errc::invalid_argument,
228 S: "file names table was not null terminated before "
229 "the end of the prologue");
230 }
231 FileNames.push_back(x: FileEntry);
232 }
233
234 return Error::success();
235}
236
237// Parse v5 directory/file entry content descriptions.
238// Returns the descriptors, or an error if we did not find a path or ran off
239// the end of the prologue.
240static llvm::Expected<ContentDescriptors>
241parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
242 DWARFDebugLine::ContentTypeTracker *ContentTypes) {
243 Error Err = Error::success();
244 ContentDescriptors Descriptors;
245 int FormatCount = DebugLineData.getU8(offset_ptr: OffsetPtr, Err: &Err);
246 bool HasPath = false;
247 for (int I = 0; I != FormatCount && !Err; ++I) {
248 ContentDescriptor Descriptor;
249 Descriptor.Type =
250 dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(offset_ptr: OffsetPtr, Err: &Err));
251 Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(offset_ptr: OffsetPtr, Err: &Err));
252 if (Descriptor.Type == dwarf::DW_LNCT_path)
253 HasPath = true;
254 if (ContentTypes)
255 ContentTypes->trackContentType(ContentType: Descriptor.Type);
256 Descriptors.push_back(Elt: Descriptor);
257 }
258
259 if (Err)
260 return createStringError(EC: errc::invalid_argument,
261 Fmt: "failed to parse entry content descriptors: %s",
262 Vals: toString(E: std::move(Err)).c_str());
263
264 if (!HasPath)
265 return createStringError(EC: errc::invalid_argument,
266 S: "failed to parse entry content descriptions"
267 " because no path was found");
268 return Descriptors;
269}
270
271static Error
272parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
273 uint64_t *OffsetPtr, const dwarf::FormParams &FormParams,
274 const DWARFContext &Ctx, const DWARFUnit *U,
275 DWARFDebugLine::ContentTypeTracker &ContentTypes,
276 std::vector<DWARFFormValue> &IncludeDirectories,
277 std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
278 // Get the directory entry description.
279 llvm::Expected<ContentDescriptors> DirDescriptors =
280 parseV5EntryFormat(DebugLineData, OffsetPtr, ContentTypes: nullptr);
281 if (!DirDescriptors)
282 return DirDescriptors.takeError();
283
284 // Get the directory entries, according to the format described above.
285 uint64_t DirEntryCount = DebugLineData.getULEB128(offset_ptr: OffsetPtr);
286 for (uint64_t I = 0; I != DirEntryCount; ++I) {
287 for (auto Descriptor : *DirDescriptors) {
288 DWARFFormValue Value(Descriptor.Form);
289 switch (Descriptor.Type) {
290 case DW_LNCT_path:
291 if (!Value.extractValue(Data: DebugLineData, OffsetPtr, FormParams, Context: &Ctx, Unit: U))
292 return createStringError(EC: errc::invalid_argument,
293 S: "failed to parse directory entry because "
294 "extracting the form value failed");
295 IncludeDirectories.push_back(x: Value);
296 break;
297 default:
298 if (!Value.skipValue(DebugInfoData: DebugLineData, OffsetPtr, Params: FormParams))
299 return createStringError(EC: errc::invalid_argument,
300 S: "failed to parse directory entry because "
301 "skipping the form value failed");
302 }
303 }
304 }
305
306 // Get the file entry description.
307 llvm::Expected<ContentDescriptors> FileDescriptors =
308 parseV5EntryFormat(DebugLineData, OffsetPtr, ContentTypes: &ContentTypes);
309 if (!FileDescriptors)
310 return FileDescriptors.takeError();
311
312 // Get the file entries, according to the format described above.
313 uint64_t FileEntryCount = DebugLineData.getULEB128(offset_ptr: OffsetPtr);
314 for (uint64_t I = 0; I != FileEntryCount; ++I) {
315 DWARFDebugLine::FileNameEntry FileEntry;
316 for (auto Descriptor : *FileDescriptors) {
317 DWARFFormValue Value(Descriptor.Form);
318 if (!Value.extractValue(Data: DebugLineData, OffsetPtr, FormParams, Context: &Ctx, Unit: U))
319 return createStringError(EC: errc::invalid_argument,
320 S: "failed to parse file entry because "
321 "extracting the form value failed");
322 switch (Descriptor.Type) {
323 case DW_LNCT_path:
324 FileEntry.Name = Value;
325 break;
326 case DW_LNCT_LLVM_source:
327 FileEntry.Source = Value;
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)
340 return createStringError(
341 EC: errc::invalid_argument,
342 S: "failed to parse file entry because the MD5 hash is invalid");
343 llvm::uninitialized_copy(Src: *Value.getAsBlock(),
344 Dst: FileEntry.Checksum.begin());
345 break;
346 default:
347 break;
348 }
349 }
350 FileNames.push_back(x: FileEntry);
351 }
352 return Error::success();
353}
354
355uint64_t DWARFDebugLine::Prologue::getLength() const {
356 uint64_t Length = PrologueLength + sizeofTotalLength() +
357 sizeof(getVersion()) + sizeofPrologueLength();
358 if (getVersion() >= 5)
359 Length += 2; // Address + Segment selector sizes.
360 return Length;
361}
362
363Error DWARFDebugLine::Prologue::parse(
364 DWARFDataExtractor DebugLineData, uint64_t *OffsetPtr,
365 function_ref<void(Error)> RecoverableErrorHandler, const DWARFContext &Ctx,
366 const DWARFUnit *U) {
367 const uint64_t PrologueOffset = *OffsetPtr;
368
369 clear();
370 DataExtractor::Cursor Cursor(*OffsetPtr);
371 std::tie(args&: TotalLength, args&: FormParams.Format) =
372 DebugLineData.getInitialLength(C&: Cursor);
373
374 DebugLineData =
375 DWARFDataExtractor(DebugLineData, Cursor.tell() + TotalLength);
376 FormParams.Version = DebugLineData.getU16(C&: Cursor);
377 if (Cursor && !versionIsSupported(Version: getVersion())) {
378 // Treat this error as unrecoverable - we cannot be sure what any of
379 // the data represents including the length field, so cannot skip it or make
380 // any reasonable assumptions.
381 *OffsetPtr = Cursor.tell();
382 return createStringError(
383 EC: errc::not_supported,
384 Fmt: "parsing line table prologue at offset 0x%8.8" PRIx64
385 ": unsupported version %" PRIu16,
386 Vals: PrologueOffset, Vals: getVersion());
387 }
388
389 if (getVersion() >= 5) {
390 FormParams.AddrSize = DebugLineData.getU8(C&: Cursor);
391 const uint8_t DataAddrSize = DebugLineData.getAddressSize();
392 const uint8_t PrologueAddrSize = getAddressSize();
393 if (Cursor) {
394 if (DataAddrSize == 0) {
395 if (PrologueAddrSize != 4 && PrologueAddrSize != 8) {
396 RecoverableErrorHandler(createStringError(
397 EC: errc::not_supported,
398 Fmt: "parsing line table prologue at offset 0x%8.8" PRIx64
399 ": invalid address size %" PRIu8,
400 Vals: PrologueOffset, Vals: PrologueAddrSize));
401 }
402 } else if (DataAddrSize != PrologueAddrSize) {
403 RecoverableErrorHandler(createStringError(
404 EC: errc::not_supported,
405 Fmt: "parsing line table prologue at offset 0x%8.8" PRIx64 ": address "
406 "size %" PRIu8 " doesn't match architecture address size %" PRIu8,
407 Vals: PrologueOffset, Vals: PrologueAddrSize, Vals: DataAddrSize));
408 }
409 }
410 SegSelectorSize = DebugLineData.getU8(C&: Cursor);
411 }
412
413 PrologueLength =
414 DebugLineData.getRelocatedValue(C&: Cursor, Size: sizeofPrologueLength());
415 const uint64_t EndPrologueOffset = PrologueLength + Cursor.tell();
416 DebugLineData = DWARFDataExtractor(DebugLineData, EndPrologueOffset);
417 MinInstLength = DebugLineData.getU8(C&: Cursor);
418 if (getVersion() >= 4)
419 MaxOpsPerInst = DebugLineData.getU8(C&: Cursor);
420 DefaultIsStmt = DebugLineData.getU8(C&: Cursor);
421 LineBase = DebugLineData.getU8(C&: Cursor);
422 LineRange = DebugLineData.getU8(C&: Cursor);
423 OpcodeBase = DebugLineData.getU8(C&: Cursor);
424
425 if (Cursor && OpcodeBase == 0) {
426 // If the opcode base is 0, we cannot read the standard opcode lengths (of
427 // which there are supposed to be one fewer than the opcode base). Assume
428 // there are no standard opcodes and continue parsing.
429 RecoverableErrorHandler(createStringError(
430 EC: errc::invalid_argument,
431 Fmt: "parsing line table prologue at offset 0x%8.8" PRIx64
432 " found opcode base of 0. Assuming no standard opcodes",
433 Vals: PrologueOffset));
434 } else if (Cursor) {
435 StandardOpcodeLengths.reserve(n: OpcodeBase - 1);
436 for (uint32_t I = 1; I < OpcodeBase; ++I) {
437 uint8_t OpLen = DebugLineData.getU8(C&: Cursor);
438 StandardOpcodeLengths.push_back(x: OpLen);
439 }
440 }
441
442 *OffsetPtr = Cursor.tell();
443 // A corrupt file name or directory table does not prevent interpretation of
444 // the main line program, so check the cursor state now so that its errors can
445 // be handled separately.
446 if (!Cursor)
447 return createStringError(
448 EC: errc::invalid_argument,
449 Fmt: "parsing line table prologue at offset 0x%8.8" PRIx64 ": %s",
450 Vals: PrologueOffset, Vals: toString(E: Cursor.takeError()).c_str());
451
452 Error E =
453 getVersion() >= 5
454 ? parseV5DirFileTables(DebugLineData, OffsetPtr, FormParams, Ctx, U,
455 ContentTypes, IncludeDirectories, FileNames)
456 : parseV2DirFileTables(DebugLineData, OffsetPtr, ContentTypes,
457 IncludeDirectories, FileNames);
458 if (E) {
459 RecoverableErrorHandler(joinErrors(
460 E1: createStringError(
461 EC: errc::invalid_argument,
462 Fmt: "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 Vals: PrologueOffset, Vals: *OffsetPtr),
466 E2: std::move(E)));
467 return Error::success();
468 }
469
470 assert(*OffsetPtr <= EndPrologueOffset);
471 if (*OffsetPtr != EndPrologueOffset) {
472 RecoverableErrorHandler(createStringError(
473 EC: errc::invalid_argument,
474 Fmt: "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 Vals: PrologueOffset, Vals: *OffsetPtr, Vals: EndPrologueOffset));
478 }
479 return Error::success();
480}
481
482DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
483
484void DWARFDebugLine::Row::postAppend() {
485 Discriminator = 0;
486 BasicBlock = false;
487 PrologueEnd = false;
488 EpilogueBegin = false;
489}
490
491void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
492 Address.Address = 0;
493 Address.SectionIndex = object::SectionedAddress::UndefSection;
494 Line = 1;
495 Column = 0;
496 File = 1;
497 Isa = 0;
498 Discriminator = 0;
499 IsStmt = DefaultIsStmt;
500 OpIndex = 0;
501 BasicBlock = false;
502 EndSequence = false;
503 PrologueEnd = false;
504 EpilogueBegin = false;
505}
506
507void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS, unsigned Indent) {
508 OS.indent(NumSpaces: Indent)
509 << "Address Line Column File ISA Discriminator OpIndex "
510 "Flags\n";
511 OS.indent(NumSpaces: Indent)
512 << "------------------ ------ ------ ------ --- ------------- ------- "
513 "-------------\n";
514}
515
516void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
517 OS << format(Fmt: "0x%16.16" PRIx64 " %6u %6u", Vals: Address.Address, Vals: Line, Vals: Column)
518 << format(Fmt: " %6u %3u %13u %7u ", Vals: File, Vals: Isa, Vals: Discriminator, Vals: OpIndex)
519 << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
520 << (PrologueEnd ? " prologue_end" : "")
521 << (EpilogueBegin ? " epilogue_begin" : "")
522 << (EndSequence ? " end_sequence" : "") << '\n';
523}
524
525DWARFDebugLine::Sequence::Sequence() { reset(); }
526
527void DWARFDebugLine::Sequence::reset() {
528 LowPC = 0;
529 HighPC = 0;
530 SectionIndex = object::SectionedAddress::UndefSection;
531 FirstRowIndex = 0;
532 LastRowIndex = 0;
533 Empty = true;
534 StmtSeqOffset = UINT64_MAX;
535}
536
537DWARFDebugLine::LineTable::LineTable() { clear(); }
538
539void DWARFDebugLine::LineTable::dump(raw_ostream &OS,
540 DIDumpOptions DumpOptions) const {
541 Prologue.dump(OS, DumpOptions);
542
543 if (!Rows.empty()) {
544 OS << '\n';
545 Row::dumpTableHeader(OS, Indent: 0);
546 for (const Row &R : Rows) {
547 R.dump(OS);
548 }
549 }
550
551 // Terminate the table with a final blank line to clearly delineate it from
552 // later dumps.
553 OS << '\n';
554}
555
556void DWARFDebugLine::LineTable::clear() {
557 Prologue.clear();
558 Rows.clear();
559 Sequences.clear();
560}
561
562DWARFDebugLine::ParsingState::ParsingState(
563 struct LineTable *LT, uint64_t TableOffset,
564 function_ref<void(Error)> ErrorHandler)
565 : LineTable(LT), LineTableOffset(TableOffset), ErrorHandler(ErrorHandler) {}
566
567void DWARFDebugLine::ParsingState::resetRowAndSequence(uint64_t Offset) {
568 Row.reset(DefaultIsStmt: 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 // Record the beginning of instruction sequence.
577 Sequence.Empty = false;
578 Sequence.LowPC = Row.Address.Address;
579 Sequence.FirstRowIndex = RowNumber;
580 }
581 LineTable->appendRow(R: Row);
582 if (Row.EndSequence) {
583 // Record the end of instruction sequence.
584 Sequence.HighPC = Row.Address.Address;
585 Sequence.LastRowIndex = RowNumber + 1;
586 Sequence.SectionIndex = Row.Address.SectionIndex;
587 if (Sequence.isValid())
588 LineTable->appendSequence(S: Sequence);
589 Sequence.reset();
590 }
591 Row.postAppend();
592}
593
594const DWARFDebugLine::LineTable *
595DWARFDebugLine::getLineTable(uint64_t Offset) const {
596 LineTableConstIter Pos = LineTableMap.find(x: Offset);
597 if (Pos != LineTableMap.end())
598 return &Pos->second;
599 return nullptr;
600}
601
602Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(
603 DWARFDataExtractor &DebugLineData, uint64_t Offset, const DWARFContext &Ctx,
604 const DWARFUnit *U, function_ref<void(Error)> RecoverableErrorHandler) {
605 if (!DebugLineData.isValidOffset(offset: Offset))
606 return createStringError(EC: errc::invalid_argument,
607 Fmt: "offset 0x%8.8" PRIx64
608 " is not a valid debug line section offset",
609 Vals: Offset);
610
611 std::pair<LineTableIter, bool> Pos =
612 LineTableMap.insert(x: LineTableMapTy::value_type(Offset, LineTable()));
613 LineTable *LT = &Pos.first->second;
614 if (Pos.second) {
615 if (Error Err =
616 LT->parse(DebugLineData, OffsetPtr: &Offset, Ctx, U, RecoverableErrorHandler))
617 return std::move(Err);
618 return LT;
619 }
620 return LT;
621}
622
623void DWARFDebugLine::clearLineTable(uint64_t Offset) {
624 LineTableMap.erase(x: Offset);
625}
626
627static StringRef getOpcodeName(uint8_t Opcode, uint8_t OpcodeBase) {
628 assert(Opcode != 0);
629 if (Opcode < OpcodeBase)
630 return LNStandardString(Standard: Opcode);
631 return "special";
632}
633
634DWARFDebugLine::ParsingState::AddrOpIndexDelta
635DWARFDebugLine::ParsingState::advanceAddrOpIndex(uint64_t OperationAdvance,
636 uint8_t Opcode,
637 uint64_t OpcodeOffset) {
638 StringRef OpcodeName = getOpcodeName(Opcode, OpcodeBase: LineTable->Prologue.OpcodeBase);
639 // For versions less than 4, the MaxOpsPerInst member is set to 0, as the
640 // maximum_operations_per_instruction field wasn't introduced until DWARFv4.
641 // Don't warn about bad values in this situation.
642 if (ReportAdvanceAddrProblem && LineTable->Prologue.getVersion() >= 4 &&
643 LineTable->Prologue.MaxOpsPerInst == 0)
644 ErrorHandler(createStringError(
645 EC: errc::invalid_argument,
646 Fmt: "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 Vals: LineTableOffset, Vals: OpcodeName.data(), Vals: OpcodeOffset));
651 // Although we are able to correctly parse line number programs with
652 // MaxOpsPerInst > 1, the rest of DWARFDebugLine and its
653 // users have not been updated to handle line information for all operations
654 // in a multi-operation instruction, so warn about potentially incorrect
655 // results.
656 if (ReportAdvanceAddrProblem && LineTable->Prologue.MaxOpsPerInst > 1)
657 ErrorHandler(createStringError(
658 EC: errc::not_supported,
659 Fmt: "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 Vals: LineTableOffset, Vals: OpcodeName.data(), Vals: OpcodeOffset,
665 Vals: LineTable->Prologue.MaxOpsPerInst));
666 if (ReportAdvanceAddrProblem && LineTable->Prologue.MinInstLength == 0)
667 ErrorHandler(
668 createStringError(EC: errc::invalid_argument,
669 Fmt: "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 Vals: LineTableOffset, Vals: OpcodeName.data(), Vals: OpcodeOffset));
674 ReportAdvanceAddrProblem = false;
675
676 // Advances the address and op_index according to DWARFv5, section 6.2.5.1:
677 //
678 // new address = address +
679 // minimum_instruction_length *
680 // ((op_index + operation advance) / maximum_operations_per_instruction)
681 //
682 // new op_index =
683 // (op_index + operation advance) % maximum_operations_per_instruction
684
685 // For versions less than 4, the MaxOpsPerInst member is set to 0, as the
686 // maximum_operations_per_instruction field wasn't introduced until DWARFv4.
687 uint8_t MaxOpsPerInst =
688 std::max(a: LineTable->Prologue.MaxOpsPerInst, b: uint8_t{1});
689
690 uint64_t AddrOffset = ((Row.OpIndex + OperationAdvance) / MaxOpsPerInst) *
691 LineTable->Prologue.MinInstLength;
692 Row.Address.Address += AddrOffset;
693
694 uint8_t PrevOpIndex = Row.OpIndex;
695 Row.OpIndex = (Row.OpIndex + OperationAdvance) % MaxOpsPerInst;
696 int16_t OpIndexDelta = static_cast<int16_t>(Row.OpIndex) - PrevOpIndex;
697
698 return {.AddrOffset: AddrOffset, .OpIndexDelta: OpIndexDelta};
699}
700
701DWARFDebugLine::ParsingState::OpcodeAdvanceResults
702DWARFDebugLine::ParsingState::advanceForOpcode(uint8_t Opcode,
703 uint64_t OpcodeOffset) {
704 assert(Opcode == DW_LNS_const_add_pc ||
705 Opcode >= LineTable->Prologue.OpcodeBase);
706 if (ReportBadLineRange && LineTable->Prologue.LineRange == 0) {
707 StringRef OpcodeName =
708 getOpcodeName(Opcode, OpcodeBase: LineTable->Prologue.OpcodeBase);
709 ErrorHandler(
710 createStringError(EC: errc::not_supported,
711 Fmt: "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 Vals: LineTableOffset, Vals: OpcodeName.data(), Vals: OpcodeOffset));
716 ReportBadLineRange = false;
717 }
718
719 uint8_t OpcodeValue = Opcode;
720 if (Opcode == DW_LNS_const_add_pc)
721 OpcodeValue = 255;
722 uint8_t AdjustedOpcode = OpcodeValue - LineTable->Prologue.OpcodeBase;
723 uint64_t OperationAdvance =
724 LineTable->Prologue.LineRange != 0
725 ? AdjustedOpcode / LineTable->Prologue.LineRange
726 : 0;
727 AddrOpIndexDelta Advance =
728 advanceAddrOpIndex(OperationAdvance, Opcode, OpcodeOffset);
729 return {.AddrDelta: Advance.AddrOffset, .OpIndexDelta: Advance.OpIndexDelta, .AdjustedOpcode: AdjustedOpcode};
730}
731
732DWARFDebugLine::ParsingState::SpecialOpcodeDelta
733DWARFDebugLine::ParsingState::handleSpecialOpcode(uint8_t Opcode,
734 uint64_t OpcodeOffset) {
735 // A special opcode value is chosen based on the amount that needs
736 // to be added to the line and address registers. The maximum line
737 // increment for a special opcode is the value of the line_base
738 // field in the header, plus the value of the line_range field,
739 // minus 1 (line base + line range - 1). If the desired line
740 // increment is greater than the maximum line increment, a standard
741 // opcode must be used instead of a special opcode. The "address
742 // advance" is calculated by dividing the desired address increment
743 // by the minimum_instruction_length field from the header. The
744 // special opcode is then calculated using the following formula:
745 //
746 // opcode = (desired line increment - line_base) +
747 // (line_range * address advance) + opcode_base
748 //
749 // If the resulting opcode is greater than 255, a standard opcode
750 // must be used instead.
751 //
752 // To decode a special opcode, subtract the opcode_base from the
753 // opcode itself to give the adjusted opcode. The amount to
754 // increment the address register is the result of the adjusted
755 // opcode divided by the line_range multiplied by the
756 // minimum_instruction_length field from the header. That is:
757 //
758 // address increment = (adjusted opcode / line_range) *
759 // minimum_instruction_length
760 //
761 // The amount to increment the line register is the line_base plus
762 // the result of the adjusted opcode modulo the line_range. That is:
763 //
764 // line increment = line_base + (adjusted opcode % line_range)
765
766 DWARFDebugLine::ParsingState::OpcodeAdvanceResults AddrAdvanceResult =
767 advanceForOpcode(Opcode, OpcodeOffset);
768 int32_t LineOffset = 0;
769 if (LineTable->Prologue.LineRange != 0)
770 LineOffset =
771 LineTable->Prologue.LineBase +
772 (AddrAdvanceResult.AdjustedOpcode % LineTable->Prologue.LineRange);
773 Row.Line += LineOffset;
774 return {.Address: AddrAdvanceResult.AddrDelta, .Line: LineOffset,
775 .OpIndex: AddrAdvanceResult.OpIndexDelta};
776}
777
778/// Parse a ULEB128 using the specified \p Cursor. \returns the parsed value on
779/// success, or std::nullopt if \p Cursor is in a failing state.
780template <typename T>
781static std::optional<T> parseULEB128(DWARFDataExtractor &Data,
782 DataExtractor::Cursor &Cursor) {
783 T Value = Data.getULEB128(C&: Cursor);
784 if (Cursor)
785 return Value;
786 return std::nullopt;
787}
788
789Error DWARFDebugLine::LineTable::parse(
790 DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
791 const DWARFContext &Ctx, const DWARFUnit *U,
792 function_ref<void(Error)> RecoverableErrorHandler, raw_ostream *OS,
793 bool Verbose) {
794 assert((OS || !Verbose) && "cannot have verbose output without stream");
795 const uint64_t DebugLineOffset = *OffsetPtr;
796
797 clear();
798
799 Error PrologueErr =
800 Prologue.parse(DebugLineData, OffsetPtr, RecoverableErrorHandler, Ctx, U);
801
802 if (OS) {
803 DIDumpOptions DumpOptions;
804 DumpOptions.Verbose = Verbose;
805 Prologue.dump(OS&: *OS, DumpOptions);
806 }
807
808 if (PrologueErr) {
809 // Ensure there is a blank line after the prologue to clearly delineate it
810 // from later dumps.
811 if (OS)
812 *OS << "\n";
813 return PrologueErr;
814 }
815
816 uint64_t ProgramLength = Prologue.TotalLength + Prologue.sizeofTotalLength();
817 if (!DebugLineData.isValidOffsetForDataOfSize(offset: DebugLineOffset,
818 length: ProgramLength)) {
819 assert(DebugLineData.size() > DebugLineOffset &&
820 "prologue parsing should handle invalid offset");
821 uint64_t BytesRemaining = DebugLineData.size() - DebugLineOffset;
822 RecoverableErrorHandler(
823 createStringError(EC: errc::invalid_argument,
824 Fmt: "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 Vals: DebugLineOffset, Vals: ProgramLength, Vals: BytesRemaining));
828 // Continue by capping the length at the number of remaining bytes.
829 ProgramLength = BytesRemaining;
830 }
831
832 // Create a DataExtractor which can only see the data up to the end of the
833 // table, to prevent reading past the end.
834 const uint64_t EndOffset = DebugLineOffset + ProgramLength;
835 DWARFDataExtractor TableData(DebugLineData, EndOffset);
836
837 // See if we should tell the data extractor the address size.
838 if (TableData.getAddressSize() == 0)
839 TableData.setAddressSize(Prologue.getAddressSize());
840 else
841 assert(Prologue.getAddressSize() == 0 ||
842 Prologue.getAddressSize() == TableData.getAddressSize());
843
844 ParsingState State(this, DebugLineOffset, RecoverableErrorHandler);
845
846 *OffsetPtr = DebugLineOffset + Prologue.getLength();
847 if (OS && *OffsetPtr < EndOffset) {
848 *OS << '\n';
849 Row::dumpTableHeader(OS&: *OS, /*Indent=*/Verbose ? 12 : 0);
850 }
851 // *OffsetPtr points to the end of the prologue - i.e. the start of the first
852 // sequence. So initialize the first sequence offset accordingly.
853 State.resetRowAndSequence(Offset: *OffsetPtr);
854
855 bool TombstonedAddress = false;
856 auto EmitRow = [&] {
857 if (!TombstonedAddress) {
858 if (Verbose) {
859 *OS << "\n";
860 OS->indent(NumSpaces: 12);
861 }
862 if (OS)
863 State.Row.dump(OS&: *OS);
864 State.appendRowToMatrix();
865 }
866 };
867 while (*OffsetPtr < EndOffset) {
868 DataExtractor::Cursor Cursor(*OffsetPtr);
869
870 if (Verbose)
871 *OS << format(Fmt: "0x%08.08" PRIx64 ": ", Vals: *OffsetPtr);
872
873 uint64_t OpcodeOffset = *OffsetPtr;
874 uint8_t Opcode = TableData.getU8(C&: Cursor);
875 size_t RowCount = Rows.size();
876
877 if (Cursor && Verbose)
878 *OS << format(Fmt: "%02.02" PRIx8 " ", Vals: Opcode);
879
880 if (Opcode == 0) {
881 // Extended Opcodes always start with a zero opcode followed by
882 // a uleb128 length so you can skip ones you don't know about
883 uint64_t Len = TableData.getULEB128(C&: Cursor);
884 uint64_t ExtOffset = Cursor.tell();
885
886 // Tolerate zero-length; assume length is correct and soldier on.
887 if (Len == 0) {
888 if (Cursor && Verbose)
889 *OS << "Badly formed extended line op (length 0)\n";
890 if (!Cursor) {
891 if (Verbose)
892 *OS << "\n";
893 RecoverableErrorHandler(Cursor.takeError());
894 }
895 *OffsetPtr = Cursor.tell();
896 continue;
897 }
898
899 uint8_t SubOpcode = TableData.getU8(C&: Cursor);
900 // OperandOffset will be the same as ExtOffset, if it was not possible to
901 // read the SubOpcode.
902 uint64_t OperandOffset = Cursor.tell();
903 if (Verbose)
904 *OS << LNExtendedString(Encoding: SubOpcode);
905 switch (SubOpcode) {
906 case DW_LNE_end_sequence:
907 // Set the end_sequence register of the state machine to true and
908 // append a row to the matrix using the current values of the
909 // state-machine registers. Then reset the registers to the initial
910 // values specified above. Every statement program sequence must end
911 // with a DW_LNE_end_sequence instruction which creates a row whose
912 // address is that of the byte after the last target machine instruction
913 // of the sequence.
914 State.Row.EndSequence = true;
915 // No need to test the Cursor is valid here, since it must be to get
916 // into this code path - if it were invalid, the default case would be
917 // followed.
918 EmitRow();
919 // Cursor now points to right after the end_sequence opcode - so points
920 // to the start of the next sequence - if one exists.
921 State.resetRowAndSequence(Offset: Cursor.tell());
922 break;
923
924 case DW_LNE_set_address:
925 // Takes a single relocatable address as an operand. The size of the
926 // operand is the size appropriate to hold an address on the target
927 // machine. Set the address register to the value given by the
928 // relocatable address and set the op_index register to 0. All of the
929 // other statement program opcodes that affect the address register
930 // add a delta to it. This instruction stores a relocatable value into
931 // it instead.
932 //
933 // Make sure the extractor knows the address size. If not, infer it
934 // from the size of the operand.
935 {
936 uint8_t ExtractorAddressSize = TableData.getAddressSize();
937 uint64_t OpcodeAddressSize = Len - 1;
938 if (ExtractorAddressSize != OpcodeAddressSize &&
939 ExtractorAddressSize != 0)
940 RecoverableErrorHandler(createStringError(
941 EC: errc::invalid_argument,
942 Fmt: "mismatching address size at offset 0x%8.8" PRIx64
943 " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,
944 Vals: ExtOffset, Vals: ExtractorAddressSize, Vals: Len - 1));
945
946 // Assume that the line table is correct and temporarily override the
947 // address size. If the size is unsupported, give up trying to read
948 // the address and continue to the next opcode.
949 if (OpcodeAddressSize != 1 && OpcodeAddressSize != 2 &&
950 OpcodeAddressSize != 4 && OpcodeAddressSize != 8) {
951 RecoverableErrorHandler(createStringError(
952 EC: errc::invalid_argument,
953 Fmt: "address size 0x%2.2" PRIx64
954 " of DW_LNE_set_address opcode at offset 0x%8.8" PRIx64
955 " is unsupported",
956 Vals: OpcodeAddressSize, Vals: ExtOffset));
957 TableData.skip(C&: Cursor, Length: OpcodeAddressSize);
958 } else {
959 TableData.setAddressSize(OpcodeAddressSize);
960 State.Row.Address.Address = TableData.getRelocatedAddress(
961 C&: Cursor, SecIx: &State.Row.Address.SectionIndex);
962 State.Row.OpIndex = 0;
963
964 uint64_t Tombstone =
965 dwarf::computeTombstoneAddress(AddressByteSize: OpcodeAddressSize);
966 TombstonedAddress = State.Row.Address.Address == Tombstone;
967
968 // Restore the address size if the extractor already had it.
969 if (ExtractorAddressSize != 0)
970 TableData.setAddressSize(ExtractorAddressSize);
971 }
972
973 if (Cursor && Verbose) {
974 *OS << " (";
975 DWARFFormValue::dumpAddress(OS&: *OS, AddressSize: OpcodeAddressSize,
976 Address: State.Row.Address.Address);
977 *OS << ')';
978 }
979 }
980 break;
981
982 case DW_LNE_define_file:
983 // Takes 4 arguments. The first is a null terminated string containing
984 // a source file name. The second is an unsigned LEB128 number
985 // representing the directory index of the directory in which the file
986 // was found. The third is an unsigned LEB128 number representing the
987 // time of last modification of the file. The fourth is an unsigned
988 // LEB128 number representing the length in bytes of the file. The time
989 // and length fields may contain LEB128(0) if the information is not
990 // available.
991 //
992 // The directory index represents an entry in the include_directories
993 // section of the statement program prologue. The index is LEB128(0)
994 // if the file was found in the current directory of the compilation,
995 // LEB128(1) if it was found in the first directory in the
996 // include_directories section, and so on. The directory index is
997 // ignored for file names that represent full path names.
998 //
999 // The files are numbered, starting at 1, in the order in which they
1000 // appear; the names in the prologue come before names defined by
1001 // the DW_LNE_define_file instruction. These numbers are used in the
1002 // the file register of the state machine.
1003 {
1004 FileNameEntry FileEntry;
1005 const char *Name = TableData.getCStr(C&: Cursor);
1006 FileEntry.Name =
1007 DWARFFormValue::createFromPValue(F: dwarf::DW_FORM_string, V: Name);
1008 FileEntry.DirIdx = TableData.getULEB128(C&: Cursor);
1009 FileEntry.ModTime = TableData.getULEB128(C&: Cursor);
1010 FileEntry.Length = TableData.getULEB128(C&: Cursor);
1011 Prologue.FileNames.push_back(x: FileEntry);
1012 if (Cursor && Verbose)
1013 *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
1014 << format(Fmt: "(0x%16.16" PRIx64 ")", Vals: FileEntry.ModTime)
1015 << ", length=" << FileEntry.Length << ")";
1016 }
1017 break;
1018
1019 case DW_LNE_set_discriminator:
1020 State.Row.Discriminator = TableData.getULEB128(C&: Cursor);
1021 if (Cursor && Verbose)
1022 *OS << " (" << State.Row.Discriminator << ")";
1023 break;
1024
1025 default:
1026 if (Cursor && Verbose)
1027 *OS << format(Fmt: "Unrecognized extended op 0x%02.02" PRIx8, Vals: SubOpcode)
1028 << format(Fmt: " length %" PRIx64, Vals: Len);
1029 // Len doesn't include the zero opcode byte or the length itself, but
1030 // it does include the sub_opcode, so we have to adjust for that.
1031 TableData.skip(C&: Cursor, Length: Len - 1);
1032 break;
1033 }
1034 // Make sure the length as recorded in the table and the standard length
1035 // for the opcode match. If they don't, continue from the end as claimed
1036 // by the table. Similarly, continue from the claimed end in the event of
1037 // a parsing error.
1038 uint64_t End = ExtOffset + Len;
1039 if (Cursor && Cursor.tell() != End)
1040 RecoverableErrorHandler(createStringError(
1041 EC: errc::illegal_byte_sequence,
1042 Fmt: "unexpected line op length at offset 0x%8.8" PRIx64
1043 " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx64,
1044 Vals: ExtOffset, Vals: Len, Vals: Cursor.tell() - ExtOffset));
1045 if (!Cursor && Verbose) {
1046 DWARFDataExtractor::Cursor ByteCursor(OperandOffset);
1047 uint8_t Byte = TableData.getU8(C&: ByteCursor);
1048 if (ByteCursor) {
1049 *OS << " (<parsing error>";
1050 do {
1051 *OS << format(Fmt: " %2.2" PRIx8, Vals: Byte);
1052 Byte = TableData.getU8(C&: ByteCursor);
1053 } while (ByteCursor);
1054 *OS << ")";
1055 }
1056
1057 // The only parse failure in this case should be if the end was reached.
1058 // In that case, throw away the error, as the main Cursor's error will
1059 // be sufficient.
1060 consumeError(Err: ByteCursor.takeError());
1061 }
1062 *OffsetPtr = End;
1063 } else if (Opcode < Prologue.OpcodeBase) {
1064 if (Verbose)
1065 *OS << LNStandardString(Standard: Opcode);
1066 switch (Opcode) {
1067 // Standard Opcodes
1068 case DW_LNS_copy:
1069 // Takes no arguments. Append a row to the matrix using the
1070 // current values of the state-machine registers.
1071 EmitRow();
1072 break;
1073
1074 case DW_LNS_advance_pc:
1075 // Takes a single unsigned LEB128 operand as the operation advance
1076 // and modifies the address and op_index registers of the state machine
1077 // according to that.
1078 if (std::optional<uint64_t> Operand =
1079 parseULEB128<uint64_t>(Data&: TableData, Cursor)) {
1080 ParsingState::AddrOpIndexDelta Advance =
1081 State.advanceAddrOpIndex(OperationAdvance: *Operand, Opcode, OpcodeOffset);
1082 if (Verbose)
1083 *OS << " (addr += " << Advance.AddrOffset
1084 << ", op-index += " << Advance.OpIndexDelta << ")";
1085 }
1086 break;
1087
1088 case DW_LNS_advance_line:
1089 // Takes a single signed LEB128 operand and adds that value to
1090 // the line register of the state machine.
1091 {
1092 int64_t LineDelta = TableData.getSLEB128(C&: Cursor);
1093 if (Cursor) {
1094 State.Row.Line += LineDelta;
1095 if (Verbose)
1096 *OS << " (" << State.Row.Line << ")";
1097 }
1098 }
1099 break;
1100
1101 case DW_LNS_set_file:
1102 // Takes a single unsigned LEB128 operand and stores it in the file
1103 // register of the state machine.
1104 if (std::optional<uint16_t> File =
1105 parseULEB128<uint16_t>(Data&: TableData, Cursor)) {
1106 State.Row.File = *File;
1107 if (Verbose)
1108 *OS << " (" << State.Row.File << ")";
1109 }
1110 break;
1111
1112 case DW_LNS_set_column:
1113 // Takes a single unsigned LEB128 operand and stores it in the
1114 // column register of the state machine.
1115 if (std::optional<uint16_t> Column =
1116 parseULEB128<uint16_t>(Data&: TableData, Cursor)) {
1117 State.Row.Column = *Column;
1118 if (Verbose)
1119 *OS << " (" << State.Row.Column << ")";
1120 }
1121 break;
1122
1123 case DW_LNS_negate_stmt:
1124 // Takes no arguments. Set the is_stmt register of the state
1125 // machine to the logical negation of its current value.
1126 State.Row.IsStmt = !State.Row.IsStmt;
1127 break;
1128
1129 case DW_LNS_set_basic_block:
1130 // Takes no arguments. Set the basic_block register of the
1131 // state machine to true
1132 State.Row.BasicBlock = true;
1133 break;
1134
1135 case DW_LNS_const_add_pc:
1136 // Takes no arguments. Advance the address and op_index registers of
1137 // the state machine by the increments corresponding to special
1138 // opcode 255. The motivation for DW_LNS_const_add_pc is this:
1139 // when the statement program needs to advance the address by a
1140 // small amount, it can use a single special opcode, which occupies
1141 // a single byte. When it needs to advance the address by up to
1142 // twice the range of the last special opcode, it can use
1143 // DW_LNS_const_add_pc followed by a special opcode, for a total
1144 // of two bytes. Only if it needs to advance the address by more
1145 // than twice that range will it need to use both DW_LNS_advance_pc
1146 // and a special opcode, requiring three or more bytes.
1147 {
1148 ParsingState::OpcodeAdvanceResults Advance =
1149 State.advanceForOpcode(Opcode, OpcodeOffset);
1150 if (Verbose)
1151 *OS << format(Fmt: " (addr += 0x%16.16" PRIx64 ", op-index += %" PRIu8
1152 ")",
1153 Vals: Advance.AddrDelta, Vals: Advance.OpIndexDelta);
1154 }
1155 break;
1156
1157 case DW_LNS_fixed_advance_pc:
1158 // Takes a single uhalf operand. Add to the address register of
1159 // the state machine the value of the (unencoded) operand and set
1160 // the op_index register to 0. This is the only extended opcode that
1161 // takes an argument that is not a variable length number.
1162 // The motivation for DW_LNS_fixed_advance_pc is this: existing
1163 // assemblers cannot emit DW_LNS_advance_pc or special opcodes because
1164 // they cannot encode LEB128 numbers or judge when the computation
1165 // of a special opcode overflows and requires the use of
1166 // DW_LNS_advance_pc. Such assemblers, however, can use
1167 // DW_LNS_fixed_advance_pc instead, sacrificing compression.
1168 {
1169 uint16_t PCOffset = TableData.getRelocatedValue(C&: Cursor, Size: 2);
1170 if (Cursor) {
1171 State.Row.Address.Address += PCOffset;
1172 State.Row.OpIndex = 0;
1173 if (Verbose)
1174 *OS << format(Fmt: " (addr += 0x%4.4" PRIx16 ", op-index = 0)",
1175 Vals: PCOffset);
1176 }
1177 }
1178 break;
1179
1180 case DW_LNS_set_prologue_end:
1181 // Takes no arguments. Set the prologue_end register of the
1182 // state machine to true
1183 State.Row.PrologueEnd = true;
1184 break;
1185
1186 case DW_LNS_set_epilogue_begin:
1187 // Takes no arguments. Set the basic_block register of the
1188 // state machine to true
1189 State.Row.EpilogueBegin = true;
1190 break;
1191
1192 case DW_LNS_set_isa:
1193 // Takes a single unsigned LEB128 operand and stores it in the
1194 // ISA register of the state machine.
1195 if (std::optional<uint8_t> Isa =
1196 parseULEB128<uint8_t>(Data&: TableData, Cursor)) {
1197 State.Row.Isa = *Isa;
1198 if (Verbose)
1199 *OS << " (" << (uint64_t)State.Row.Isa << ")";
1200 }
1201 break;
1202
1203 default:
1204 // Handle any unknown standard opcodes here. We know the lengths
1205 // of such opcodes because they are specified in the prologue
1206 // as a multiple of LEB128 operands for each opcode.
1207 {
1208 assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
1209 if (Verbose)
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 =
1215 parseULEB128<uint64_t>(Data&: TableData, Cursor))
1216 Operands.push_back(x: *Value);
1217 else
1218 break;
1219 }
1220 if (Verbose && !Operands.empty()) {
1221 *OS << " (operands: ";
1222 bool First = true;
1223 for (uint64_t Value : Operands) {
1224 if (!First)
1225 *OS << ", ";
1226 First = false;
1227 *OS << format(Fmt: "0x%16.16" PRIx64, Vals: Value);
1228 }
1229 if (Verbose)
1230 *OS << ')';
1231 }
1232 }
1233 break;
1234 }
1235
1236 *OffsetPtr = Cursor.tell();
1237 } else {
1238 // Special Opcodes.
1239 ParsingState::SpecialOpcodeDelta Delta =
1240 State.handleSpecialOpcode(Opcode, OpcodeOffset);
1241
1242 if (Verbose)
1243 *OS << "address += " << Delta.Address << ", line += " << Delta.Line
1244 << ", op-index += " << Delta.OpIndex;
1245 EmitRow();
1246 *OffsetPtr = Cursor.tell();
1247 }
1248
1249 // When a row is added to the matrix, it is also dumped, which includes a
1250 // new line already, so don't add an extra one.
1251 if (Verbose && Rows.size() == RowCount)
1252 *OS << "\n";
1253
1254 // Most parse failures other than when parsing extended opcodes are due to
1255 // failures to read ULEBs. Bail out of parsing, since we don't know where to
1256 // continue reading from as there is no stated length for such byte
1257 // sequences. Print the final trailing new line if needed before doing so.
1258 if (!Cursor && Opcode != 0) {
1259 if (Verbose)
1260 *OS << "\n";
1261 return Cursor.takeError();
1262 }
1263
1264 if (!Cursor)
1265 RecoverableErrorHandler(Cursor.takeError());
1266 }
1267
1268 if (!State.Sequence.Empty)
1269 RecoverableErrorHandler(createStringError(
1270 EC: errc::illegal_byte_sequence,
1271 Fmt: "last sequence in debug line table at offset 0x%8.8" PRIx64
1272 " is not terminated",
1273 Vals: DebugLineOffset));
1274
1275 // Sort all sequences so that address lookup will work faster.
1276 if (!Sequences.empty()) {
1277 llvm::stable_sort(Range&: Sequences, C: Sequence::orderByHighPC);
1278 // Note: actually, instruction address ranges of sequences should not
1279 // overlap (in shared objects and executables). If they do, the address
1280 // lookup would still work, though, but result would be ambiguous.
1281 // We don't report warning in this case. For example,
1282 // sometimes .so compiled from multiple object files contains a few
1283 // rudimentary sequences for address ranges [0x0, 0xsomething).
1284 // Address ranges may also overlap when using ICF.
1285 }
1286
1287 // Terminate the table with a final blank line to clearly delineate it from
1288 // later dumps.
1289 if (OS)
1290 *OS << "\n";
1291
1292 return Error::success();
1293}
1294
1295uint32_t DWARFDebugLine::LineTable::findRowInSeq(
1296 const DWARFDebugLine::Sequence &Seq,
1297 object::SectionedAddress Address) const {
1298 if (!Seq.containsPC(PC: Address))
1299 return UnknownRowIndex;
1300 assert(Seq.SectionIndex == Address.SectionIndex);
1301 // In some cases, e.g. first instruction in a function, the compiler generates
1302 // two entries, both with the same address. We want the last one.
1303 //
1304 // In general we want a non-empty range: the last row whose address is less
1305 // than or equal to Address. This can be computed as upper_bound - 1.
1306 //
1307 // TODO: This function, and its users, needs to be update to return multiple
1308 // rows for bundles with multiple op-indexes.
1309 DWARFDebugLine::Row Row;
1310 Row.Address = Address;
1311 RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
1312 RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
1313 assert(FirstRow->Address.Address <= Row.Address.Address &&
1314 Row.Address.Address < LastRow[-1].Address.Address);
1315 RowIter RowPos = std::upper_bound(first: FirstRow + 1, last: LastRow - 1, val: Row,
1316 comp: DWARFDebugLine::Row::orderByAddress) -
1317 1;
1318 assert(Seq.SectionIndex == RowPos->Address.SectionIndex);
1319 return RowPos - Rows.begin();
1320}
1321
1322uint32_t
1323DWARFDebugLine::LineTable::lookupAddress(object::SectionedAddress Address,
1324 bool *IsApproximateLine) const {
1325
1326 // Search for relocatable addresses
1327 uint32_t Result = lookupAddressImpl(Address, IsApproximateLine);
1328
1329 if (Result != UnknownRowIndex ||
1330 Address.SectionIndex == object::SectionedAddress::UndefSection)
1331 return Result;
1332
1333 // Search for absolute addresses
1334 Address.SectionIndex = object::SectionedAddress::UndefSection;
1335 return lookupAddressImpl(Address, IsApproximateLine);
1336}
1337
1338uint32_t
1339DWARFDebugLine::LineTable::lookupAddressImpl(object::SectionedAddress Address,
1340 bool *IsApproximateLine) const {
1341 assert((!IsApproximateLine || !*IsApproximateLine) &&
1342 "Make sure IsApproximateLine is appropriately "
1343 "initialized, if provided");
1344 // First, find an instruction sequence containing the given address.
1345 DWARFDebugLine::Sequence Sequence;
1346 Sequence.SectionIndex = Address.SectionIndex;
1347 Sequence.HighPC = Address.Address;
1348 SequenceIter It = llvm::upper_bound(Range: Sequences, Value&: Sequence,
1349 C: DWARFDebugLine::Sequence::orderByHighPC);
1350 if (It == Sequences.end() || It->SectionIndex != Address.SectionIndex)
1351 return UnknownRowIndex;
1352
1353 uint32_t RowIndex = findRowInSeq(Seq: *It, Address);
1354 if (RowIndex == UnknownRowIndex || !IsApproximateLine)
1355 return RowIndex;
1356
1357 // Approximation will only be attempted if a valid RowIndex exists.
1358 uint32_t ApproxRowIndex = RowIndex;
1359 // Approximation Loop
1360 for (; ApproxRowIndex >= It->FirstRowIndex; --ApproxRowIndex) {
1361 if (Rows[ApproxRowIndex].Line)
1362 return ApproxRowIndex;
1363 *IsApproximateLine = true;
1364 }
1365 // Approximation Loop fails to find the valid ApproxRowIndex
1366 if (ApproxRowIndex < It->FirstRowIndex)
1367 *IsApproximateLine = false;
1368
1369 return RowIndex;
1370}
1371
1372bool DWARFDebugLine::LineTable::lookupAddressRange(
1373 object::SectionedAddress Address, uint64_t Size,
1374 std::vector<uint32_t> &Result,
1375 std::optional<uint64_t> StmtSequenceOffset) const {
1376
1377 // Search for relocatable addresses
1378 if (lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset))
1379 return true;
1380
1381 if (Address.SectionIndex == object::SectionedAddress::UndefSection)
1382 return false;
1383
1384 // Search for absolute addresses
1385 Address.SectionIndex = object::SectionedAddress::UndefSection;
1386 return lookupAddressRangeImpl(Address, Size, Result, StmtSequenceOffset);
1387}
1388
1389bool DWARFDebugLine::LineTable::lookupAddressRangeImpl(
1390 object::SectionedAddress Address, uint64_t Size,
1391 std::vector<uint32_t> &Result,
1392 std::optional<uint64_t> StmtSequenceOffset) const {
1393 if (Sequences.empty())
1394 return false;
1395 uint64_t EndAddr = Address.Address + Size;
1396 // First, find an instruction sequence containing the given address.
1397 DWARFDebugLine::Sequence Sequence;
1398 Sequence.SectionIndex = Address.SectionIndex;
1399 Sequence.HighPC = Address.Address;
1400 SequenceIter LastSeq = Sequences.end();
1401 SequenceIter SeqPos;
1402
1403 if (StmtSequenceOffset) {
1404 // If we have a statement sequence offset, find the specific sequence.
1405 // Linear search for sequence with matching StmtSeqOffset
1406 SeqPos = std::find_if(first: Sequences.begin(), last: LastSeq,
1407 pred: [&](const DWARFDebugLine::Sequence &S) {
1408 return S.StmtSeqOffset == *StmtSequenceOffset;
1409 });
1410
1411 // If sequence not found, return false
1412 if (SeqPos == LastSeq)
1413 return false;
1414
1415 // Set LastSeq to the next sequence since we only want the one matching
1416 // sequence (sequences are guaranteed to have unique StmtSeqOffset)
1417 LastSeq = SeqPos + 1;
1418 } else {
1419 // No specific sequence requested, find first sequence containing address
1420 SeqPos = std::upper_bound(first: Sequences.begin(), last: LastSeq, val: Sequence,
1421 comp: DWARFDebugLine::Sequence::orderByHighPC);
1422 if (SeqPos == LastSeq)
1423 return false;
1424 }
1425
1426 // If the start sequence doesn't contain the address, nothing to do
1427 if (!SeqPos->containsPC(PC: Address))
1428 return false;
1429
1430 SequenceIter StartPos = SeqPos;
1431
1432 // Process sequences that overlap with the desired range
1433 while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
1434 const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
1435 // For the first sequence, we need to find which row in the sequence is the
1436 // first in our range.
1437 uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
1438 if (SeqPos == StartPos)
1439 FirstRowIndex = findRowInSeq(Seq: CurSeq, Address);
1440
1441 // Figure out the last row in the range.
1442 uint32_t LastRowIndex =
1443 findRowInSeq(Seq: CurSeq, Address: {.Address: EndAddr - 1, .SectionIndex: Address.SectionIndex});
1444 if (LastRowIndex == UnknownRowIndex)
1445 LastRowIndex = CurSeq.LastRowIndex - 1;
1446
1447 assert(FirstRowIndex != UnknownRowIndex);
1448 assert(LastRowIndex != UnknownRowIndex);
1449
1450 for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
1451 Result.push_back(x: I);
1452 }
1453
1454 ++SeqPos;
1455 }
1456
1457 return true;
1458}
1459
1460std::optional<StringRef>
1461DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
1462 FileLineInfoKind Kind) const {
1463 if (Kind == FileLineInfoKind::None || !Prologue.hasFileAtIndex(FileIndex))
1464 return std::nullopt;
1465 const FileNameEntry &Entry = Prologue.getFileNameEntry(Index: FileIndex);
1466 if (auto E = dwarf::toString(V: Entry.Source))
1467 return StringRef(*E);
1468 return std::nullopt;
1469}
1470
1471static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
1472 // Debug info can contain paths from any OS, not necessarily
1473 // an OS we're currently running on. Moreover different compilation units can
1474 // be compiled on different operating systems and linked together later.
1475 return sys::path::is_absolute(path: Path, style: sys::path::Style::posix) ||
1476 sys::path::is_absolute(path: Path, style: sys::path::Style::windows);
1477}
1478
1479bool DWARFDebugLine::Prologue::getFileNameByIndex(
1480 uint64_t FileIndex, StringRef CompDir, FileLineInfoKind Kind,
1481 std::string &Result, sys::path::Style Style) const {
1482 if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
1483 return false;
1484 const FileNameEntry &Entry = getFileNameEntry(Index: FileIndex);
1485 auto E = dwarf::toString(V: Entry.Name);
1486 if (!E)
1487 return false;
1488 StringRef FileName = *E;
1489 if (Kind == FileLineInfoKind::RawValue ||
1490 isPathAbsoluteOnWindowsOrPosix(Path: FileName)) {
1491 Result = std::string(FileName);
1492 return true;
1493 }
1494 if (Kind == FileLineInfoKind::BaseNameOnly) {
1495 Result = std::string(llvm::sys::path::filename(path: FileName));
1496 return true;
1497 }
1498
1499 SmallString<16> FilePath;
1500 StringRef IncludeDir;
1501 // Be defensive about the contents of Entry.
1502 if (getVersion() >= 5) {
1503 // DirIdx 0 is the compilation directory, so don't include it for
1504 // relative names.
1505 if ((Entry.DirIdx != 0 || Kind != FileLineInfoKind::RelativeFilePath) &&
1506 Entry.DirIdx < IncludeDirectories.size())
1507 IncludeDir = dwarf::toStringRef(V: IncludeDirectories[Entry.DirIdx]);
1508 } else {
1509 if (0 < Entry.DirIdx && Entry.DirIdx <= IncludeDirectories.size())
1510 IncludeDir = dwarf::toStringRef(V: IncludeDirectories[Entry.DirIdx - 1]);
1511 }
1512
1513 // For absolute paths only, include the compilation directory of compile unit,
1514 // unless v5 DirIdx == 0 (IncludeDir indicates the compilation directory). We
1515 // know that FileName is not absolute, the only way to have an absolute path
1516 // at this point would be if IncludeDir is absolute.
1517 if (Kind == FileLineInfoKind::AbsoluteFilePath &&
1518 (getVersion() < 5 || Entry.DirIdx != 0) && !CompDir.empty() &&
1519 !isPathAbsoluteOnWindowsOrPosix(Path: IncludeDir))
1520 sys::path::append(path&: FilePath, style: Style, a: CompDir);
1521
1522 assert((Kind == FileLineInfoKind::AbsoluteFilePath ||
1523 Kind == FileLineInfoKind::RelativeFilePath) &&
1524 "invalid FileLineInfo Kind");
1525
1526 // sys::path::append skips empty strings.
1527 sys::path::append(path&: FilePath, style: Style, a: IncludeDir, b: FileName);
1528 Result = std::string(FilePath);
1529 return true;
1530}
1531
1532bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
1533 object::SectionedAddress Address, bool Approximate, const char *CompDir,
1534 FileLineInfoKind Kind, DILineInfo &Result) const {
1535 // Get the index of row we're looking for in the line table.
1536 uint32_t RowIndex =
1537 lookupAddress(Address, IsApproximateLine: Approximate ? &Result.IsApproximateLine : nullptr);
1538 if (RowIndex == -1U)
1539 return false;
1540 // Take file number and line/column from the row.
1541 const auto &Row = Rows[RowIndex];
1542 if (!getFileNameByIndex(FileIndex: Row.File, CompDir, Kind, Result&: Result.FileName))
1543 return false;
1544 Result.Line = Row.Line;
1545 Result.Column = Row.Column;
1546 Result.Discriminator = Row.Discriminator;
1547 Result.Source = getSourceByIndex(FileIndex: Row.File, Kind);
1548 return true;
1549}
1550
1551bool DWARFDebugLine::LineTable::getDirectoryForEntry(
1552 const FileNameEntry &Entry, std::string &Directory) const {
1553 if (Prologue.getVersion() >= 5) {
1554 if (Entry.DirIdx < Prologue.IncludeDirectories.size()) {
1555 Directory =
1556 dwarf::toString(V: Prologue.IncludeDirectories[Entry.DirIdx], Default: "");
1557 return true;
1558 }
1559 return false;
1560 }
1561 if (0 < Entry.DirIdx && Entry.DirIdx <= Prologue.IncludeDirectories.size()) {
1562 Directory =
1563 dwarf::toString(V: Prologue.IncludeDirectories[Entry.DirIdx - 1], Default: "");
1564 return true;
1565 }
1566 return false;
1567}
1568
1569// We want to supply the Unit associated with a .debug_line[.dwo] table when
1570// we dump it, if possible, but still dump the table even if there isn't a Unit.
1571// Therefore, collect up handles on all the Units that point into the
1572// line-table section.
1573static DWARFDebugLine::SectionParser::LineToUnitMap
1574buildLineToUnitMap(DWARFUnitVector::iterator_range Units) {
1575 DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit;
1576 for (const auto &U : Units)
1577 if (auto CUDIE = U->getUnitDIE())
1578 if (auto StmtOffset = toSectionOffset(V: CUDIE.find(Attr: DW_AT_stmt_list)))
1579 LineToUnit.insert(x: std::make_pair(x&: *StmtOffset, y: &*U));
1580 return LineToUnit;
1581}
1582
1583DWARFDebugLine::SectionParser::SectionParser(
1584 DWARFDataExtractor &Data, const DWARFContext &C,
1585 DWARFUnitVector::iterator_range Units)
1586 : DebugLineData(Data), Context(C) {
1587 LineToUnit = buildLineToUnitMap(Units);
1588 if (!DebugLineData.isValidOffset(offset: Offset))
1589 Done = true;
1590}
1591
1592bool DWARFDebugLine::Prologue::totalLengthIsValid() const {
1593 return TotalLength != 0u;
1594}
1595
1596DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
1597 function_ref<void(Error)> RecoverableErrorHandler,
1598 function_ref<void(Error)> UnrecoverableErrorHandler, raw_ostream *OS,
1599 bool Verbose) {
1600 assert(DebugLineData.isValidOffset(Offset) &&
1601 "parsing should have terminated");
1602 DWARFUnit *U = prepareToParse(Offset);
1603 uint64_t OldOffset = Offset;
1604 LineTable LT;
1605 if (Error Err = LT.parse(DebugLineData, OffsetPtr: &Offset, Ctx: Context, U,
1606 RecoverableErrorHandler, OS, Verbose))
1607 UnrecoverableErrorHandler(std::move(Err));
1608 moveToNextTable(OldOffset, P: LT.Prologue);
1609 return LT;
1610}
1611
1612void DWARFDebugLine::SectionParser::skip(
1613 function_ref<void(Error)> RecoverableErrorHandler,
1614 function_ref<void(Error)> UnrecoverableErrorHandler) {
1615 assert(DebugLineData.isValidOffset(Offset) &&
1616 "parsing should have terminated");
1617 DWARFUnit *U = prepareToParse(Offset);
1618 uint64_t OldOffset = Offset;
1619 LineTable LT;
1620 if (Error Err = LT.Prologue.parse(DebugLineData, OffsetPtr: &Offset,
1621 RecoverableErrorHandler, Ctx: Context, U))
1622 UnrecoverableErrorHandler(std::move(Err));
1623 moveToNextTable(OldOffset, P: LT.Prologue);
1624}
1625
1626DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint64_t Offset) {
1627 DWARFUnit *U = nullptr;
1628 auto It = LineToUnit.find(x: 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) {
1636 DataExtractor::Cursor Cursor(Offset);
1637 auto [TotalLength, _] = DebugLineData.getInitialLength(C&: Cursor);
1638 DWARFDataExtractor HeaderData(DebugLineData, Cursor.tell() + TotalLength);
1639 uint16_t Version = HeaderData.getU16(C&: Cursor);
1640 if (!Cursor) {
1641 // Ignore any error here.
1642 // If this is not the end of the section parseNext() will still be
1643 // attempted, where this error will occur again (and can be handled).
1644 consumeError(Err: Cursor.takeError());
1645 return false;
1646 }
1647 return versionIsSupported(Version);
1648}
1649
1650void DWARFDebugLine::SectionParser::moveToNextTable(uint64_t OldOffset,
1651 const Prologue &P) {
1652 // If the length field is not valid, we don't know where the next table is, so
1653 // cannot continue to parse. Mark the parser as done, and leave the Offset
1654 // value as it currently is. This will be the end of the bad length field.
1655 if (!P.totalLengthIsValid()) {
1656 Done = true;
1657 return;
1658 }
1659
1660 Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();
1661 if (!DebugLineData.isValidOffset(offset: Offset)) {
1662 Done = true;
1663 return;
1664 }
1665
1666 // Heuristic: If the version is valid, then this is probably a line table.
1667 // Otherwise, the offset might need alignment (to a 4 or 8 byte boundary).
1668 if (hasValidVersion(Offset))
1669 return;
1670
1671 // ARM C/C++ Compiler aligns each line table to word boundaries and pads out
1672 // the .debug_line section to a word multiple. Note that in the specification
1673 // this does not seem forbidden since each unit has a DW_AT_stmt_list.
1674 for (unsigned Align : {4, 8}) {
1675 uint64_t AlignedOffset = alignTo(Value: Offset, Align);
1676 if (!DebugLineData.isValidOffset(offset: AlignedOffset)) {
1677 // This is almost certainly not another line table but some alignment
1678 // padding. This assumes the alignments tested are ordered, and are
1679 // smaller than the header size (which is true for 4 and 8).
1680 Done = true;
1681 return;
1682 }
1683 if (hasValidVersion(Offset: AlignedOffset)) {
1684 Offset = AlignedOffset;
1685 break;
1686 }
1687 }
1688}
1689