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