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