Line data Source code
1 : //===- DWARFDebugLine.cpp -------------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
11 : #include "llvm/ADT/Optional.h"
12 : #include "llvm/ADT/SmallString.h"
13 : #include "llvm/ADT/SmallVector.h"
14 : #include "llvm/ADT/StringRef.h"
15 : #include "llvm/BinaryFormat/Dwarf.h"
16 : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
17 : #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
18 : #include "llvm/Support/Errc.h"
19 : #include "llvm/Support/Format.h"
20 : #include "llvm/Support/Path.h"
21 : #include "llvm/Support/WithColor.h"
22 : #include "llvm/Support/raw_ostream.h"
23 : #include <algorithm>
24 : #include <cassert>
25 : #include <cinttypes>
26 : #include <cstdint>
27 : #include <cstdio>
28 : #include <utility>
29 :
30 : using namespace llvm;
31 : using namespace dwarf;
32 :
33 : using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
34 :
35 : namespace {
36 :
37 : struct ContentDescriptor {
38 : dwarf::LineNumberEntryFormat Type;
39 : dwarf::Form Form;
40 : };
41 :
42 : using ContentDescriptors = SmallVector<ContentDescriptor, 4>;
43 :
44 : } // end anonmyous namespace
45 :
46 188 : void DWARFDebugLine::ContentTypeTracker::trackContentType(
47 : dwarf::LineNumberEntryFormat ContentType) {
48 188 : switch (ContentType) {
49 4 : case dwarf::DW_LNCT_timestamp:
50 4 : HasModTime = true;
51 4 : break;
52 4 : case dwarf::DW_LNCT_size:
53 4 : HasLength = true;
54 4 : break;
55 35 : case dwarf::DW_LNCT_MD5:
56 35 : HasMD5 = true;
57 35 : break;
58 5 : case dwarf::DW_LNCT_LLVM_source:
59 5 : HasSource = true;
60 5 : break;
61 : default:
62 : // We only care about values we consider optional, and new values may be
63 : // added in the vendor extension range, so we do not match exhaustively.
64 : break;
65 : }
66 188 : }
67 :
68 2944 : DWARFDebugLine::Prologue::Prologue() { clear(); }
69 :
70 5742 : void DWARFDebugLine::Prologue::clear() {
71 5742 : TotalLength = PrologueLength = 0;
72 5742 : SegSelectorSize = 0;
73 5742 : MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
74 5742 : OpcodeBase = 0;
75 5742 : FormParams = dwarf::FormParams({0, 0, DWARF32});
76 5742 : ContentTypes = ContentTypeTracker();
77 : StandardOpcodeLengths.clear();
78 : IncludeDirectories.clear();
79 : FileNames.clear();
80 5742 : }
81 :
82 349 : void DWARFDebugLine::Prologue::dump(raw_ostream &OS,
83 : DIDumpOptions DumpOptions) const {
84 349 : OS << "Line table prologue:\n"
85 698 : << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength)
86 698 : << format(" version: %u\n", getVersion());
87 349 : if (getVersion() >= 5)
88 82 : OS << format(" address_size: %u\n", getAddressSize())
89 41 : << format(" seg_select_size: %u\n", SegSelectorSize);
90 698 : OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
91 349 : << format(" min_inst_length: %u\n", MinInstLength)
92 508 : << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
93 349 : << format(" default_is_stmt: %u\n", DefaultIsStmt)
94 349 : << format(" line_base: %i\n", LineBase)
95 349 : << format(" line_range: %u\n", LineRange)
96 349 : << format(" opcode_base: %u\n", OpcodeBase);
97 :
98 8708 : for (uint32_t I = 0; I != StandardOpcodeLengths.size(); ++I)
99 4005 : OS << format("standard_opcode_lengths[%s] = %u\n",
100 4005 : LNStandardString(I + 1).data(), StandardOpcodeLengths[I]);
101 :
102 349 : if (!IncludeDirectories.empty()) {
103 : // DWARF v5 starts directory indexes at 0.
104 79 : uint32_t DirBase = getVersion() >= 5 ? 0 : 1;
105 275 : for (uint32_t I = 0; I != IncludeDirectories.size(); ++I) {
106 234 : OS << format("include_directories[%3u] = ", I + DirBase);
107 234 : IncludeDirectories[I].dump(OS, DumpOptions);
108 : OS << '\n';
109 : }
110 : }
111 :
112 349 : if (!FileNames.empty()) {
113 : // DWARF v5 starts file indexes at 0.
114 316 : uint32_t FileBase = getVersion() >= 5 ? 0 : 1;
115 1051 : for (uint32_t I = 0; I != FileNames.size(); ++I) {
116 : const FileNameEntry &FileEntry = FileNames[I];
117 838 : OS << format("file_names[%3u]:\n", I + FileBase);
118 419 : OS << " name: ";
119 419 : FileEntry.Name.dump(OS, DumpOptions);
120 : OS << '\n'
121 838 : << format(" dir_index: %" PRIu64 "\n", FileEntry.DirIdx);
122 419 : if (ContentTypes.HasMD5)
123 78 : OS << " md5_checksum: " << FileEntry.Checksum.digest() << '\n';
124 419 : if (ContentTypes.HasModTime)
125 690 : OS << format(" mod_time: 0x%8.8" PRIx64 "\n", FileEntry.ModTime);
126 419 : if (ContentTypes.HasLength)
127 690 : OS << format(" length: 0x%8.8" PRIx64 "\n", FileEntry.Length);
128 419 : if (ContentTypes.HasSource) {
129 9 : OS << " source: ";
130 9 : FileEntry.Source.dump(OS, DumpOptions);
131 : OS << '\n';
132 : }
133 : }
134 : }
135 349 : }
136 :
137 : // Parse v2-v4 directory and file tables.
138 : static void
139 0 : parseV2DirFileTables(const DWARFDataExtractor &DebugLineData,
140 : uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
141 : DWARFDebugLine::ContentTypeTracker &ContentTypes,
142 : std::vector<DWARFFormValue> &IncludeDirectories,
143 : std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
144 0 : while (*OffsetPtr < EndPrologueOffset) {
145 0 : StringRef S = DebugLineData.getCStrRef(OffsetPtr);
146 0 : if (S.empty())
147 : break;
148 : DWARFFormValue Dir(dwarf::DW_FORM_string);
149 : Dir.setPValue(S.data());
150 0 : IncludeDirectories.push_back(Dir);
151 : }
152 :
153 0 : while (*OffsetPtr < EndPrologueOffset) {
154 0 : StringRef Name = DebugLineData.getCStrRef(OffsetPtr);
155 0 : if (Name.empty())
156 : break;
157 : DWARFDebugLine::FileNameEntry FileEntry;
158 : FileEntry.Name.setForm(dwarf::DW_FORM_string);
159 : FileEntry.Name.setPValue(Name.data());
160 0 : FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
161 0 : FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
162 0 : FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
163 0 : FileNames.push_back(FileEntry);
164 : }
165 :
166 0 : ContentTypes.HasModTime = true;
167 0 : ContentTypes.HasLength = true;
168 0 : }
169 :
170 : // Parse v5 directory/file entry content descriptions.
171 : // Returns the descriptors, or an empty vector if we did not find a path or
172 : // ran off the end of the prologue.
173 : static ContentDescriptors
174 154 : parseV5EntryFormat(const DWARFDataExtractor &DebugLineData, uint32_t
175 : *OffsetPtr, uint64_t EndPrologueOffset, DWARFDebugLine::ContentTypeTracker
176 : *ContentTypes) {
177 154 : ContentDescriptors Descriptors;
178 154 : int FormatCount = DebugLineData.getU8(OffsetPtr);
179 : bool HasPath = false;
180 420 : for (int I = 0; I != FormatCount; ++I) {
181 266 : if (*OffsetPtr >= EndPrologueOffset)
182 0 : return ContentDescriptors();
183 : ContentDescriptor Descriptor;
184 266 : Descriptor.Type =
185 266 : dwarf::LineNumberEntryFormat(DebugLineData.getULEB128(OffsetPtr));
186 266 : Descriptor.Form = dwarf::Form(DebugLineData.getULEB128(OffsetPtr));
187 266 : if (Descriptor.Type == dwarf::DW_LNCT_path)
188 : HasPath = true;
189 266 : if (ContentTypes)
190 188 : ContentTypes->trackContentType(Descriptor.Type);
191 266 : Descriptors.push_back(Descriptor);
192 : }
193 154 : return HasPath ? Descriptors : ContentDescriptors();
194 : }
195 :
196 : static bool
197 0 : parseV5DirFileTables(const DWARFDataExtractor &DebugLineData,
198 : uint32_t *OffsetPtr, uint64_t EndPrologueOffset,
199 : const dwarf::FormParams &FormParams,
200 : const DWARFContext &Ctx, const DWARFUnit *U,
201 : DWARFDebugLine::ContentTypeTracker &ContentTypes,
202 : std::vector<DWARFFormValue> &IncludeDirectories,
203 : std::vector<DWARFDebugLine::FileNameEntry> &FileNames) {
204 : // Get the directory entry description.
205 : ContentDescriptors DirDescriptors =
206 0 : parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset, nullptr);
207 0 : if (DirDescriptors.empty())
208 0 : return false;
209 :
210 : // Get the directory entries, according to the format described above.
211 0 : int DirEntryCount = DebugLineData.getU8(OffsetPtr);
212 0 : for (int I = 0; I != DirEntryCount; ++I) {
213 0 : if (*OffsetPtr >= EndPrologueOffset)
214 0 : return false;
215 0 : for (auto Descriptor : DirDescriptors) {
216 0 : DWARFFormValue Value(Descriptor.Form);
217 0 : switch (Descriptor.Type) {
218 0 : case DW_LNCT_path:
219 0 : if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
220 0 : return false;
221 0 : IncludeDirectories.push_back(Value);
222 0 : break;
223 0 : default:
224 0 : if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams))
225 0 : return false;
226 : }
227 : }
228 : }
229 :
230 : // Get the file entry description.
231 : ContentDescriptors FileDescriptors =
232 : parseV5EntryFormat(DebugLineData, OffsetPtr, EndPrologueOffset,
233 0 : &ContentTypes);
234 0 : if (FileDescriptors.empty())
235 0 : return false;
236 :
237 : // Get the file entries, according to the format described above.
238 0 : int FileEntryCount = DebugLineData.getU8(OffsetPtr);
239 0 : for (int I = 0; I != FileEntryCount; ++I) {
240 0 : if (*OffsetPtr >= EndPrologueOffset)
241 0 : return false;
242 : DWARFDebugLine::FileNameEntry FileEntry;
243 0 : for (auto Descriptor : FileDescriptors) {
244 : DWARFFormValue Value(Descriptor.Form);
245 0 : if (!Value.extractValue(DebugLineData, OffsetPtr, FormParams, &Ctx, U))
246 0 : return false;
247 0 : switch (Descriptor.Type) {
248 0 : case DW_LNCT_path:
249 0 : FileEntry.Name = Value;
250 0 : break;
251 0 : case DW_LNCT_LLVM_source:
252 0 : FileEntry.Source = Value;
253 0 : break;
254 0 : case DW_LNCT_directory_index:
255 0 : FileEntry.DirIdx = Value.getAsUnsignedConstant().getValue();
256 0 : break;
257 0 : case DW_LNCT_timestamp:
258 0 : FileEntry.ModTime = Value.getAsUnsignedConstant().getValue();
259 0 : break;
260 0 : case DW_LNCT_size:
261 0 : FileEntry.Length = Value.getAsUnsignedConstant().getValue();
262 0 : break;
263 : case DW_LNCT_MD5:
264 : assert(Value.getAsBlock().getValue().size() == 16);
265 0 : std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16,
266 : FileEntry.Checksum.Bytes.begin());
267 0 : break;
268 : default:
269 : break;
270 : }
271 : }
272 0 : FileNames.push_back(FileEntry);
273 : }
274 : return true;
275 : }
276 :
277 1430 : Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
278 : uint32_t *OffsetPtr,
279 : const DWARFContext &Ctx,
280 : const DWARFUnit *U) {
281 1430 : const uint64_t PrologueOffset = *OffsetPtr;
282 :
283 1430 : clear();
284 1430 : TotalLength = DebugLineData.getU32(OffsetPtr);
285 1430 : if (TotalLength == UINT32_MAX) {
286 16 : FormParams.Format = dwarf::DWARF64;
287 16 : TotalLength = DebugLineData.getU64(OffsetPtr);
288 1414 : } else if (TotalLength >= 0xffffff00) {
289 : return createStringError(errc::invalid_argument,
290 : "parsing line table prologue at offset 0x%8.8" PRIx64
291 : " unsupported reserved unit length found of value 0x%8.8" PRIx64,
292 14 : PrologueOffset, TotalLength);
293 : }
294 1423 : FormParams.Version = DebugLineData.getU16(OffsetPtr);
295 1423 : if (getVersion() < 2)
296 : return createStringError(errc::not_supported,
297 : "parsing line table prologue at offset 0x%8.8" PRIx64
298 : " found unsupported version 0x%2.2" PRIx16,
299 28 : PrologueOffset, getVersion());
300 :
301 1409 : if (getVersion() >= 5) {
302 80 : FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
303 : assert((DebugLineData.getAddressSize() == 0 ||
304 : DebugLineData.getAddressSize() == getAddressSize()) &&
305 : "Line table header and data extractor disagree");
306 80 : SegSelectorSize = DebugLineData.getU8(OffsetPtr);
307 : }
308 :
309 1409 : PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
310 1409 : const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
311 1409 : MinInstLength = DebugLineData.getU8(OffsetPtr);
312 1409 : if (getVersion() >= 4)
313 598 : MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
314 1409 : DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
315 1409 : LineBase = DebugLineData.getU8(OffsetPtr);
316 1409 : LineRange = DebugLineData.getU8(OffsetPtr);
317 1409 : OpcodeBase = DebugLineData.getU8(OffsetPtr);
318 :
319 1409 : StandardOpcodeLengths.reserve(OpcodeBase - 1);
320 18051 : for (uint32_t I = 1; I < OpcodeBase; ++I) {
321 16642 : uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
322 16642 : StandardOpcodeLengths.push_back(OpLen);
323 : }
324 :
325 1409 : if (getVersion() >= 5) {
326 80 : if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
327 80 : FormParams, Ctx, U, ContentTypes,
328 80 : IncludeDirectories, FileNames)) {
329 : return createStringError(errc::invalid_argument,
330 : "parsing line table prologue at 0x%8.8" PRIx64
331 : " found an invalid directory or file table description at"
332 : " 0x%8.8" PRIx64,
333 12 : PrologueOffset, (uint64_t)*OffsetPtr);
334 : }
335 : } else
336 1329 : parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
337 1329 : ContentTypes, IncludeDirectories, FileNames);
338 :
339 1403 : if (*OffsetPtr != EndPrologueOffset)
340 : return createStringError(errc::invalid_argument,
341 : "parsing line table prologue at 0x%8.8" PRIx64
342 : " should have ended at 0x%8.8" PRIx64
343 : " but it ended at 0x%8.8" PRIx64,
344 40 : PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
345 : return Error::success();
346 : }
347 :
348 2139 : DWARFDebugLine::Row::Row(bool DefaultIsStmt) { reset(DefaultIsStmt); }
349 :
350 8094 : void DWARFDebugLine::Row::postAppend() {
351 8094 : BasicBlock = false;
352 8094 : PrologueEnd = false;
353 8094 : EpilogueBegin = false;
354 8094 : }
355 :
356 4845 : void DWARFDebugLine::Row::reset(bool DefaultIsStmt) {
357 4845 : Address = 0;
358 4845 : Line = 1;
359 4845 : Column = 0;
360 4845 : File = 1;
361 4845 : Isa = 0;
362 4845 : Discriminator = 0;
363 4845 : IsStmt = DefaultIsStmt;
364 4845 : BasicBlock = false;
365 4845 : EndSequence = false;
366 4845 : PrologueEnd = false;
367 4845 : EpilogueBegin = false;
368 4845 : }
369 :
370 134 : void DWARFDebugLine::Row::dumpTableHeader(raw_ostream &OS) {
371 134 : OS << "Address Line Column File ISA Discriminator Flags\n"
372 : << "------------------ ------ ------ ------ --- ------------- "
373 134 : "-------------\n";
374 134 : }
375 :
376 1716 : void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
377 3432 : OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
378 3432 : << format(" %6u %3u %13u ", File, Isa, Discriminator)
379 3701 : << (IsStmt ? " is_stmt" : "") << (BasicBlock ? " basic_block" : "")
380 3074 : << (PrologueEnd ? " prologue_end" : "")
381 3432 : << (EpilogueBegin ? " epilogue_begin" : "")
382 3117 : << (EndSequence ? " end_sequence" : "") << '\n';
383 1716 : }
384 :
385 2848 : DWARFDebugLine::Sequence::Sequence() { reset(); }
386 :
387 6892 : void DWARFDebugLine::Sequence::reset() {
388 6892 : LowPC = 0;
389 6892 : HighPC = 0;
390 6892 : FirstRowIndex = 0;
391 6892 : LastRowIndex = 0;
392 6892 : Empty = true;
393 6892 : }
394 :
395 1440 : DWARFDebugLine::LineTable::LineTable() { clear(); }
396 :
397 151 : void DWARFDebugLine::LineTable::dump(raw_ostream &OS,
398 : DIDumpOptions DumpOptions) const {
399 151 : Prologue.dump(OS, DumpOptions);
400 : OS << '\n';
401 :
402 151 : if (!Rows.empty()) {
403 132 : Row::dumpTableHeader(OS);
404 932 : for (const Row &R : Rows) {
405 800 : R.dump(OS);
406 : }
407 : }
408 151 : }
409 :
410 2840 : void DWARFDebugLine::LineTable::clear() {
411 2840 : Prologue.clear();
412 : Rows.clear();
413 : Sequences.clear();
414 2840 : }
415 :
416 1368 : DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
417 1368 : : LineTable(LT) {
418 1368 : resetRowAndSequence();
419 1368 : }
420 :
421 2706 : void DWARFDebugLine::ParsingState::resetRowAndSequence() {
422 2706 : Row.reset(LineTable->Prologue.DefaultIsStmt);
423 2706 : Sequence.reset();
424 2706 : }
425 :
426 8094 : void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t Offset) {
427 8094 : if (Sequence.Empty) {
428 : // Record the beginning of instruction sequence.
429 1344 : Sequence.Empty = false;
430 1344 : Sequence.LowPC = Row.Address;
431 1344 : Sequence.FirstRowIndex = RowNumber;
432 : }
433 8094 : ++RowNumber;
434 8094 : LineTable->appendRow(Row);
435 8094 : if (Row.EndSequence) {
436 : // Record the end of instruction sequence.
437 1338 : Sequence.HighPC = Row.Address;
438 1338 : Sequence.LastRowIndex = RowNumber;
439 : if (Sequence.isValid())
440 1307 : LineTable->appendSequence(Sequence);
441 1338 : Sequence.reset();
442 : }
443 8094 : Row.postAppend();
444 8094 : }
445 :
446 : const DWARFDebugLine::LineTable *
447 3590 : DWARFDebugLine::getLineTable(uint32_t Offset) const {
448 : LineTableConstIter Pos = LineTableMap.find(Offset);
449 3590 : if (Pos != LineTableMap.end())
450 2729 : return &Pos->second;
451 : return nullptr;
452 : }
453 :
454 879 : Expected<const DWARFDebugLine::LineTable *> DWARFDebugLine::getOrParseLineTable(
455 : DWARFDataExtractor &DebugLineData, uint32_t Offset, const DWARFContext &Ctx,
456 : const DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) {
457 1758 : if (!DebugLineData.isValidOffset(Offset))
458 4 : return createStringError(errc::invalid_argument, "offset 0x%8.8" PRIx32
459 : " is not a valid debug line section offset",
460 : Offset);
461 :
462 : std::pair<LineTableIter, bool> Pos =
463 1750 : LineTableMap.insert(LineTableMapTy::value_type(Offset, LineTable()));
464 875 : LineTable *LT = &Pos.first->second;
465 875 : if (Pos.second) {
466 865 : if (Error Err =
467 1730 : LT->parse(DebugLineData, &Offset, Ctx, U, RecoverableErrorCallback))
468 : return std::move(Err);
469 : return LT;
470 : }
471 : return LT;
472 : }
473 :
474 1400 : Error DWARFDebugLine::LineTable::parse(
475 : DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
476 : const DWARFContext &Ctx, const DWARFUnit *U,
477 : std::function<void(Error)> RecoverableErrorCallback, raw_ostream *OS) {
478 1400 : const uint32_t DebugLineOffset = *OffsetPtr;
479 :
480 1400 : clear();
481 :
482 1400 : Error PrologueErr = Prologue.parse(DebugLineData, OffsetPtr, Ctx, U);
483 :
484 1400 : if (OS) {
485 : // The presence of OS signals verbose dumping.
486 198 : DIDumpOptions DumpOptions;
487 198 : DumpOptions.Verbose = true;
488 198 : Prologue.dump(*OS, DumpOptions);
489 : }
490 :
491 1400 : if (PrologueErr)
492 : return PrologueErr;
493 :
494 : const uint32_t EndOffset =
495 1368 : DebugLineOffset + Prologue.TotalLength + Prologue.sizeofTotalLength();
496 :
497 : // See if we should tell the data extractor the address size.
498 1368 : if (DebugLineData.getAddressSize() == 0)
499 48 : DebugLineData.setAddressSize(Prologue.getAddressSize());
500 : else
501 : assert(Prologue.getAddressSize() == 0 ||
502 : Prologue.getAddressSize() == DebugLineData.getAddressSize());
503 :
504 1368 : ParsingState State(this);
505 :
506 20438 : while (*OffsetPtr < EndOffset) {
507 19078 : if (OS)
508 2153 : *OS << format("0x%08.08" PRIx32 ": ", *OffsetPtr);
509 :
510 19078 : uint8_t Opcode = DebugLineData.getU8(OffsetPtr);
511 :
512 19078 : if (OS)
513 2153 : *OS << format("%02.02" PRIx8 " ", Opcode);
514 :
515 19078 : if (Opcode == 0) {
516 : // Extended Opcodes always start with a zero opcode followed by
517 : // a uleb128 length so you can skip ones you don't know about
518 3066 : uint64_t Len = DebugLineData.getULEB128(OffsetPtr);
519 3066 : uint32_t ExtOffset = *OffsetPtr;
520 :
521 : // Tolerate zero-length; assume length is correct and soldier on.
522 3066 : if (Len == 0) {
523 2 : if (OS)
524 2 : *OS << "Badly formed extended line op (length 0)\n";
525 2 : continue;
526 : }
527 :
528 3064 : uint8_t SubOpcode = DebugLineData.getU8(OffsetPtr);
529 3064 : if (OS)
530 262 : *OS << LNExtendedString(SubOpcode);
531 3064 : switch (SubOpcode) {
532 1338 : case DW_LNE_end_sequence:
533 : // Set the end_sequence register of the state machine to true and
534 : // append a row to the matrix using the current values of the
535 : // state-machine registers. Then reset the registers to the initial
536 : // values specified above. Every statement program sequence must end
537 : // with a DW_LNE_end_sequence instruction which creates a row whose
538 : // address is that of the byte after the last target machine instruction
539 : // of the sequence.
540 1338 : State.Row.EndSequence = true;
541 1338 : State.appendRowToMatrix(*OffsetPtr);
542 1338 : if (OS) {
543 130 : *OS << "\n";
544 130 : OS->indent(12);
545 130 : State.Row.dump(*OS);
546 : }
547 1338 : State.resetRowAndSequence();
548 1338 : break;
549 :
550 1332 : case DW_LNE_set_address:
551 : // Takes a single relocatable address as an operand. The size of the
552 : // operand is the size appropriate to hold an address on the target
553 : // machine. Set the address register to the value given by the
554 : // relocatable address. All of the other statement program opcodes
555 : // that affect the address register add a delta to it. This instruction
556 : // stores a relocatable value into it instead.
557 : //
558 : // Make sure the extractor knows the address size. If not, infer it
559 : // from the size of the operand.
560 1332 : if (DebugLineData.getAddressSize() == 0)
561 19 : DebugLineData.setAddressSize(Len - 1);
562 1313 : else if (DebugLineData.getAddressSize() != Len - 1) {
563 : return createStringError(errc::invalid_argument,
564 : "mismatching address size at offset 0x%8.8" PRIx32
565 : " expected 0x%2.2" PRIx8 " found 0x%2.2" PRIx64,
566 4 : ExtOffset, DebugLineData.getAddressSize(),
567 4 : Len - 1);
568 : }
569 1330 : State.Row.Address = DebugLineData.getRelocatedAddress(OffsetPtr);
570 1330 : if (OS)
571 130 : *OS << format(" (0x%16.16" PRIx64 ")", State.Row.Address);
572 : break;
573 :
574 : case DW_LNE_define_file:
575 : // Takes 4 arguments. The first is a null terminated string containing
576 : // a source file name. The second is an unsigned LEB128 number
577 : // representing the directory index of the directory in which the file
578 : // was found. The third is an unsigned LEB128 number representing the
579 : // time of last modification of the file. The fourth is an unsigned
580 : // LEB128 number representing the length in bytes of the file. The time
581 : // and length fields may contain LEB128(0) if the information is not
582 : // available.
583 : //
584 : // The directory index represents an entry in the include_directories
585 : // section of the statement program prologue. The index is LEB128(0)
586 : // if the file was found in the current directory of the compilation,
587 : // LEB128(1) if it was found in the first directory in the
588 : // include_directories section, and so on. The directory index is
589 : // ignored for file names that represent full path names.
590 : //
591 : // The files are numbered, starting at 1, in the order in which they
592 : // appear; the names in the prologue come before names defined by
593 : // the DW_LNE_define_file instruction. These numbers are used in the
594 : // the file register of the state machine.
595 : {
596 : FileNameEntry FileEntry;
597 0 : const char *Name = DebugLineData.getCStr(OffsetPtr);
598 : FileEntry.Name.setForm(dwarf::DW_FORM_string);
599 : FileEntry.Name.setPValue(Name);
600 0 : FileEntry.DirIdx = DebugLineData.getULEB128(OffsetPtr);
601 0 : FileEntry.ModTime = DebugLineData.getULEB128(OffsetPtr);
602 0 : FileEntry.Length = DebugLineData.getULEB128(OffsetPtr);
603 0 : Prologue.FileNames.push_back(FileEntry);
604 0 : if (OS)
605 0 : *OS << " (" << Name << ", dir=" << FileEntry.DirIdx << ", mod_time="
606 0 : << format("(0x%16.16" PRIx64 ")", FileEntry.ModTime)
607 0 : << ", length=" << FileEntry.Length << ")";
608 : }
609 0 : break;
610 :
611 392 : case DW_LNE_set_discriminator:
612 392 : State.Row.Discriminator = DebugLineData.getULEB128(OffsetPtr);
613 392 : if (OS)
614 0 : *OS << " (" << State.Row.Discriminator << ")";
615 : break;
616 :
617 2 : default:
618 2 : if (OS)
619 2 : *OS << format("Unrecognized extended op 0x%02.02" PRIx8, SubOpcode)
620 4 : << format(" length %" PRIx64, Len);
621 : // Len doesn't include the zero opcode byte or the length itself, but
622 : // it does include the sub_opcode, so we have to adjust for that.
623 2 : (*OffsetPtr) += Len - 1;
624 2 : break;
625 : }
626 : // Make sure the stated and parsed lengths are the same.
627 : // Otherwise we have an unparseable line-number program.
628 3062 : if (*OffsetPtr - ExtOffset != Len)
629 : return createStringError(errc::illegal_byte_sequence,
630 : "unexpected line op length at offset 0x%8.8" PRIx32
631 : " expected 0x%2.2" PRIx64 " found 0x%2.2" PRIx32,
632 12 : ExtOffset, Len, *OffsetPtr - ExtOffset);
633 16012 : } else if (Opcode < Prologue.OpcodeBase) {
634 10214 : if (OS)
635 1185 : *OS << LNStandardString(Opcode);
636 10214 : switch (Opcode) {
637 : // Standard Opcodes
638 958 : case DW_LNS_copy:
639 : // Takes no arguments. Append a row to the matrix using the
640 : // current values of the state-machine registers. Then set
641 : // the basic_block register to false.
642 958 : State.appendRowToMatrix(*OffsetPtr);
643 958 : if (OS) {
644 79 : *OS << "\n";
645 79 : OS->indent(12);
646 79 : State.Row.dump(*OS);
647 79 : *OS << "\n";
648 : }
649 : break;
650 :
651 1684 : case DW_LNS_advance_pc:
652 : // Takes a single unsigned LEB128 operand, multiplies it by the
653 : // min_inst_length field of the prologue, and adds the
654 : // result to the address register of the state machine.
655 : {
656 : uint64_t AddrOffset =
657 1684 : DebugLineData.getULEB128(OffsetPtr) * Prologue.MinInstLength;
658 1684 : State.Row.Address += AddrOffset;
659 1684 : if (OS)
660 159 : *OS << " (" << AddrOffset << ")";
661 : }
662 : break;
663 :
664 1172 : case DW_LNS_advance_line:
665 : // Takes a single signed LEB128 operand and adds that value to
666 : // the line register of the state machine.
667 1172 : State.Row.Line += DebugLineData.getSLEB128(OffsetPtr);
668 1172 : if (OS)
669 160 : *OS << " (" << State.Row.Line << ")";
670 : break;
671 :
672 145 : case DW_LNS_set_file:
673 : // Takes a single unsigned LEB128 operand and stores it in the file
674 : // register of the state machine.
675 145 : State.Row.File = DebugLineData.getULEB128(OffsetPtr);
676 145 : if (OS)
677 12 : *OS << " (" << State.Row.File << ")";
678 : break;
679 :
680 2476 : case DW_LNS_set_column:
681 : // Takes a single unsigned LEB128 operand and stores it in the
682 : // column register of the state machine.
683 2476 : State.Row.Column = DebugLineData.getULEB128(OffsetPtr);
684 2476 : if (OS)
685 302 : *OS << " (" << State.Row.Column << ")";
686 : break;
687 :
688 1145 : case DW_LNS_negate_stmt:
689 : // Takes no arguments. Set the is_stmt register of the state
690 : // machine to the logical negation of its current value.
691 1145 : State.Row.IsStmt = !State.Row.IsStmt;
692 1145 : break;
693 :
694 0 : case DW_LNS_set_basic_block:
695 : // Takes no arguments. Set the basic_block register of the
696 : // state machine to true
697 0 : State.Row.BasicBlock = true;
698 0 : break;
699 :
700 891 : case DW_LNS_const_add_pc:
701 : // Takes no arguments. Add to the address register of the state
702 : // machine the address increment value corresponding to special
703 : // opcode 255. The motivation for DW_LNS_const_add_pc is this:
704 : // when the statement program needs to advance the address by a
705 : // small amount, it can use a single special opcode, which occupies
706 : // a single byte. When it needs to advance the address by up to
707 : // twice the range of the last special opcode, it can use
708 : // DW_LNS_const_add_pc followed by a special opcode, for a total
709 : // of two bytes. Only if it needs to advance the address by more
710 : // than twice that range will it need to use both DW_LNS_advance_pc
711 : // and a special opcode, requiring three or more bytes.
712 : {
713 891 : uint8_t AdjustOpcode = 255 - Prologue.OpcodeBase;
714 : uint64_t AddrOffset =
715 891 : (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
716 891 : State.Row.Address += AddrOffset;
717 891 : if (OS)
718 : *OS
719 110 : << format(" (0x%16.16" PRIx64 ")", AddrOffset);
720 : }
721 : break;
722 :
723 0 : case DW_LNS_fixed_advance_pc:
724 : // Takes a single uhalf operand. Add to the address register of
725 : // the state machine the value of the (unencoded) operand. This
726 : // is the only extended opcode that takes an argument that is not
727 : // a variable length number. The motivation for DW_LNS_fixed_advance_pc
728 : // is this: existing assemblers cannot emit DW_LNS_advance_pc or
729 : // special opcodes because they cannot encode LEB128 numbers or
730 : // judge when the computation of a special opcode overflows and
731 : // requires the use of DW_LNS_advance_pc. Such assemblers, however,
732 : // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
733 : {
734 0 : uint16_t PCOffset = DebugLineData.getU16(OffsetPtr);
735 0 : State.Row.Address += PCOffset;
736 0 : if (OS)
737 : *OS
738 0 : << format(" (0x%16.16" PRIx64 ")", PCOffset);
739 : }
740 : break;
741 :
742 1743 : case DW_LNS_set_prologue_end:
743 : // Takes no arguments. Set the prologue_end register of the
744 : // state machine to true
745 1743 : State.Row.PrologueEnd = true;
746 1743 : break;
747 :
748 0 : case DW_LNS_set_epilogue_begin:
749 : // Takes no arguments. Set the basic_block register of the
750 : // state machine to true
751 0 : State.Row.EpilogueBegin = true;
752 0 : break;
753 :
754 0 : case DW_LNS_set_isa:
755 : // Takes a single unsigned LEB128 operand and stores it in the
756 : // column register of the state machine.
757 0 : State.Row.Isa = DebugLineData.getULEB128(OffsetPtr);
758 0 : if (OS)
759 0 : *OS << " (" << State.Row.Isa << ")";
760 : break;
761 :
762 0 : default:
763 : // Handle any unknown standard opcodes here. We know the lengths
764 : // of such opcodes because they are specified in the prologue
765 : // as a multiple of LEB128 operands for each opcode.
766 : {
767 : assert(Opcode - 1U < Prologue.StandardOpcodeLengths.size());
768 0 : uint8_t OpcodeLength = Prologue.StandardOpcodeLengths[Opcode - 1];
769 0 : for (uint8_t I = 0; I < OpcodeLength; ++I) {
770 0 : uint64_t Value = DebugLineData.getULEB128(OffsetPtr);
771 0 : if (OS)
772 0 : *OS << format("Skipping ULEB128 value: 0x%16.16" PRIx64 ")\n",
773 0 : Value);
774 0 : }
775 : }
776 : break;
777 : }
778 : } else {
779 : // Special Opcodes
780 :
781 : // A special opcode value is chosen based on the amount that needs
782 : // to be added to the line and address registers. The maximum line
783 : // increment for a special opcode is the value of the line_base
784 : // field in the header, plus the value of the line_range field,
785 : // minus 1 (line base + line range - 1). If the desired line
786 : // increment is greater than the maximum line increment, a standard
787 : // opcode must be used instead of a special opcode. The "address
788 : // advance" is calculated by dividing the desired address increment
789 : // by the minimum_instruction_length field from the header. The
790 : // special opcode is then calculated using the following formula:
791 : //
792 : // opcode = (desired line increment - line_base) +
793 : // (line_range * address advance) + opcode_base
794 : //
795 : // If the resulting opcode is greater than 255, a standard opcode
796 : // must be used instead.
797 : //
798 : // To decode a special opcode, subtract the opcode_base from the
799 : // opcode itself to give the adjusted opcode. The amount to
800 : // increment the address register is the result of the adjusted
801 : // opcode divided by the line_range multiplied by the
802 : // minimum_instruction_length field from the header. That is:
803 : //
804 : // address increment = (adjusted opcode / line_range) *
805 : // minimum_instruction_length
806 : //
807 : // The amount to increment the line register is the line_base plus
808 : // the result of the adjusted opcode modulo the line_range. That is:
809 : //
810 : // line increment = line_base + (adjusted opcode % line_range)
811 :
812 5798 : uint8_t AdjustOpcode = Opcode - Prologue.OpcodeBase;
813 5798 : uint64_t AddrOffset =
814 5798 : (AdjustOpcode / Prologue.LineRange) * Prologue.MinInstLength;
815 5798 : int32_t LineOffset =
816 5798 : Prologue.LineBase + (AdjustOpcode % Prologue.LineRange);
817 5798 : State.Row.Line += LineOffset;
818 5798 : State.Row.Address += AddrOffset;
819 :
820 5798 : if (OS) {
821 704 : *OS << "address += " << ((uint32_t)AdjustOpcode)
822 1408 : << ", line += " << LineOffset << "\n";
823 704 : OS->indent(12);
824 704 : State.Row.dump(*OS);
825 : }
826 :
827 5798 : State.appendRowToMatrix(*OffsetPtr);
828 : // Reset discriminator to 0.
829 5798 : State.Row.Discriminator = 0;
830 : }
831 19068 : if(OS)
832 2148 : *OS << "\n";
833 : }
834 :
835 1360 : if (!State.Sequence.Empty)
836 : RecoverableErrorCallback(
837 12 : createStringError(errc::illegal_byte_sequence,
838 : "last sequence in debug line table is not terminated!"));
839 :
840 : // Sort all sequences so that address lookup will work faster.
841 1360 : if (!Sequences.empty()) {
842 : llvm::sort(Sequences, Sequence::orderByLowPC);
843 : // Note: actually, instruction address ranges of sequences should not
844 : // overlap (in shared objects and executables). If they do, the address
845 : // lookup would still work, though, but result would be ambiguous.
846 : // We don't report warning in this case. For example,
847 : // sometimes .so compiled from multiple object files contains a few
848 : // rudimentary sequences for address ranges [0x0, 0xsomething).
849 : }
850 :
851 : return Error::success();
852 : }
853 :
854 : uint32_t
855 774 : DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &Seq,
856 : uint64_t Address) const {
857 774 : if (!Seq.containsPC(Address))
858 3 : return UnknownRowIndex;
859 : // Search for instruction address in the rows describing the sequence.
860 : // Rows are stored in a vector, so we may use arithmetical operations with
861 : // iterators.
862 771 : DWARFDebugLine::Row Row;
863 771 : Row.Address = Address;
864 771 : RowIter FirstRow = Rows.begin() + Seq.FirstRowIndex;
865 771 : RowIter LastRow = Rows.begin() + Seq.LastRowIndex;
866 : LineTable::RowIter RowPos = std::lower_bound(
867 771 : FirstRow, LastRow, Row, DWARFDebugLine::Row::orderByAddress);
868 771 : if (RowPos == LastRow) {
869 0 : return Seq.LastRowIndex - 1;
870 : }
871 771 : uint32_t Index = Seq.FirstRowIndex + (RowPos - FirstRow);
872 771 : if (RowPos->Address > Address) {
873 561 : if (RowPos == FirstRow)
874 0 : return UnknownRowIndex;
875 : else
876 561 : Index--;
877 : }
878 : return Index;
879 : }
880 :
881 745 : uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t Address) const {
882 745 : if (Sequences.empty())
883 18 : return UnknownRowIndex;
884 : // First, find an instruction sequence containing the given address.
885 727 : DWARFDebugLine::Sequence Sequence;
886 727 : Sequence.LowPC = Address;
887 727 : SequenceIter FirstSeq = Sequences.begin();
888 727 : SequenceIter LastSeq = Sequences.end();
889 : SequenceIter SeqPos = std::lower_bound(
890 727 : FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
891 727 : DWARFDebugLine::Sequence FoundSeq;
892 727 : if (SeqPos == LastSeq) {
893 662 : FoundSeq = Sequences.back();
894 65 : } else if (SeqPos->LowPC == Address) {
895 45 : FoundSeq = *SeqPos;
896 : } else {
897 20 : if (SeqPos == FirstSeq)
898 5 : return UnknownRowIndex;
899 15 : FoundSeq = *(SeqPos - 1);
900 : }
901 722 : return findRowInSeq(FoundSeq, Address);
902 : }
903 :
904 26 : bool DWARFDebugLine::LineTable::lookupAddressRange(
905 : uint64_t Address, uint64_t Size, std::vector<uint32_t> &Result) const {
906 26 : if (Sequences.empty())
907 : return false;
908 26 : uint64_t EndAddr = Address + Size;
909 : // First, find an instruction sequence containing the given address.
910 26 : DWARFDebugLine::Sequence Sequence;
911 26 : Sequence.LowPC = Address;
912 26 : SequenceIter FirstSeq = Sequences.begin();
913 26 : SequenceIter LastSeq = Sequences.end();
914 : SequenceIter SeqPos = std::lower_bound(
915 26 : FirstSeq, LastSeq, Sequence, DWARFDebugLine::Sequence::orderByLowPC);
916 26 : if (SeqPos == LastSeq || SeqPos->LowPC != Address) {
917 14 : if (SeqPos == FirstSeq)
918 : return false;
919 : SeqPos--;
920 : }
921 26 : if (!SeqPos->containsPC(Address))
922 : return false;
923 :
924 : SequenceIter StartPos = SeqPos;
925 :
926 : // Add the rows from the first sequence to the vector, starting with the
927 : // index we just calculated
928 :
929 52 : while (SeqPos != LastSeq && SeqPos->LowPC < EndAddr) {
930 : const DWARFDebugLine::Sequence &CurSeq = *SeqPos;
931 : // For the first sequence, we need to find which row in the sequence is the
932 : // first in our range.
933 26 : uint32_t FirstRowIndex = CurSeq.FirstRowIndex;
934 26 : if (SeqPos == StartPos)
935 26 : FirstRowIndex = findRowInSeq(CurSeq, Address);
936 :
937 : // Figure out the last row in the range.
938 26 : uint32_t LastRowIndex = findRowInSeq(CurSeq, EndAddr - 1);
939 26 : if (LastRowIndex == UnknownRowIndex)
940 0 : LastRowIndex = CurSeq.LastRowIndex - 1;
941 :
942 : assert(FirstRowIndex != UnknownRowIndex);
943 : assert(LastRowIndex != UnknownRowIndex);
944 :
945 142 : for (uint32_t I = FirstRowIndex; I <= LastRowIndex; ++I) {
946 116 : Result.push_back(I);
947 : }
948 :
949 : ++SeqPos;
950 : }
951 :
952 : return true;
953 : }
954 :
955 4433 : bool DWARFDebugLine::LineTable::hasFileAtIndex(uint64_t FileIndex) const {
956 4433 : return FileIndex != 0 && FileIndex <= Prologue.FileNames.size();
957 : }
958 :
959 719 : Optional<StringRef> DWARFDebugLine::LineTable::getSourceByIndex(uint64_t FileIndex,
960 : FileLineInfoKind Kind) const {
961 719 : if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
962 : return None;
963 719 : const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
964 719 : if (Optional<const char *> source = Entry.Source.getAsCString())
965 24 : return StringRef(*source);
966 : return None;
967 : }
968 :
969 6664 : static bool isPathAbsoluteOnWindowsOrPosix(const Twine &Path) {
970 : // Debug info can contain paths from any OS, not necessarily
971 : // an OS we're currently running on. Moreover different compilation units can
972 : // be compiled on different operating systems and linked together later.
973 13096 : return sys::path::is_absolute(Path, sys::path::Style::posix) ||
974 6432 : sys::path::is_absolute(Path, sys::path::Style::windows);
975 : }
976 :
977 3614 : bool DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
978 : const char *CompDir,
979 : FileLineInfoKind Kind,
980 : std::string &Result) const {
981 3614 : if (Kind == FileLineInfoKind::None || !hasFileAtIndex(FileIndex))
982 0 : return false;
983 3614 : const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
984 3614 : StringRef FileName = Entry.Name.getAsCString().getValue();
985 7109 : if (Kind != FileLineInfoKind::AbsoluteFilePath ||
986 7109 : isPathAbsoluteOnWindowsOrPosix(FileName)) {
987 127 : Result = FileName;
988 127 : return true;
989 : }
990 :
991 : SmallString<16> FilePath;
992 3487 : uint64_t IncludeDirIndex = Entry.DirIdx;
993 3487 : StringRef IncludeDir;
994 : // Be defensive about the contents of Entry.
995 3487 : if (IncludeDirIndex > 0 &&
996 432 : IncludeDirIndex <= Prologue.IncludeDirectories.size())
997 431 : IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1]
998 862 : .getAsCString()
999 : .getValue();
1000 :
1001 : // We may still need to append compilation directory of compile unit.
1002 : // We know that FileName is not absolute, the only way to have an
1003 : // absolute path at this point would be if IncludeDir is absolute.
1004 6656 : if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
1005 6656 : !isPathAbsoluteOnWindowsOrPosix(IncludeDir))
1006 2938 : sys::path::append(FilePath, CompDir);
1007 :
1008 : // sys::path::append skips empty strings.
1009 3487 : sys::path::append(FilePath, IncludeDir, FileName);
1010 6974 : Result = FilePath.str();
1011 : return true;
1012 : }
1013 :
1014 745 : bool DWARFDebugLine::LineTable::getFileLineInfoForAddress(
1015 : uint64_t Address, const char *CompDir, FileLineInfoKind Kind,
1016 : DILineInfo &Result) const {
1017 : // Get the index of row we're looking for in the line table.
1018 745 : uint32_t RowIndex = lookupAddress(Address);
1019 745 : if (RowIndex == -1U)
1020 : return false;
1021 : // Take file number and line/column from the row.
1022 719 : const auto &Row = Rows[RowIndex];
1023 719 : if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
1024 : return false;
1025 719 : Result.Line = Row.Line;
1026 719 : Result.Column = Row.Column;
1027 719 : Result.Discriminator = Row.Discriminator;
1028 719 : Result.Source = getSourceByIndex(Row.File, Kind);
1029 719 : return true;
1030 : }
1031 :
1032 : // We want to supply the Unit associated with a .debug_line[.dwo] table when
1033 : // we dump it, if possible, but still dump the table even if there isn't a Unit.
1034 : // Therefore, collect up handles on all the Units that point into the
1035 : // line-table section.
1036 : static DWARFDebugLine::SectionParser::LineToUnitMap
1037 250 : buildLineToUnitMap(DWARFDebugLine::SectionParser::cu_range CUs,
1038 : DWARFDebugLine::SectionParser::tu_range TUs) {
1039 : DWARFDebugLine::SectionParser::LineToUnitMap LineToUnit;
1040 561 : for (const auto &CU : CUs)
1041 311 : if (auto CUDIE = CU->getUnitDIE())
1042 620 : if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list)))
1043 285 : LineToUnit.insert(std::make_pair(*StmtOffset, &*CU));
1044 298 : for (const auto &TU : TUs)
1045 48 : if (auto TUDIE = TU->getUnitDIE())
1046 96 : if (auto StmtOffset = toSectionOffset(TUDIE.find(DW_AT_stmt_list)))
1047 45 : LineToUnit.insert(std::make_pair(*StmtOffset, &*TU));
1048 250 : return LineToUnit;
1049 : }
1050 :
1051 250 : DWARFDebugLine::SectionParser::SectionParser(DWARFDataExtractor &Data,
1052 : const DWARFContext &C,
1053 250 : cu_range CUs, tu_range TUs)
1054 250 : : DebugLineData(Data), Context(C) {
1055 250 : LineToUnit = buildLineToUnitMap(CUs, TUs);
1056 500 : if (!DebugLineData.isValidOffset(Offset))
1057 3 : Done = true;
1058 250 : }
1059 :
1060 386 : bool DWARFDebugLine::Prologue::totalLengthIsValid() const {
1061 386 : return TotalLength == 0xffffffff || TotalLength < 0xffffff00;
1062 : }
1063 :
1064 356 : DWARFDebugLine::LineTable DWARFDebugLine::SectionParser::parseNext(
1065 : function_ref<void(Error)> RecoverableErrorCallback,
1066 : function_ref<void(Error)> UnrecoverableErrorCallback, raw_ostream *OS) {
1067 : assert(DebugLineData.isValidOffset(Offset) &&
1068 : "parsing should have terminated");
1069 356 : DWARFUnit *U = prepareToParse(Offset);
1070 356 : uint32_t OldOffset = Offset;
1071 356 : LineTable LT;
1072 356 : if (Error Err = LT.parse(DebugLineData, &Offset, Context, U,
1073 712 : RecoverableErrorCallback, OS))
1074 46 : UnrecoverableErrorCallback(std::move(Err));
1075 356 : moveToNextTable(OldOffset, LT.Prologue);
1076 356 : return LT;
1077 : }
1078 :
1079 30 : void DWARFDebugLine::SectionParser::skip(
1080 : function_ref<void(Error)> ErrorCallback) {
1081 : assert(DebugLineData.isValidOffset(Offset) &&
1082 : "parsing should have terminated");
1083 30 : DWARFUnit *U = prepareToParse(Offset);
1084 30 : uint32_t OldOffset = Offset;
1085 60 : LineTable LT;
1086 60 : if (Error Err = LT.Prologue.parse(DebugLineData, &Offset, Context, U))
1087 30 : ErrorCallback(std::move(Err));
1088 30 : moveToNextTable(OldOffset, LT.Prologue);
1089 30 : }
1090 :
1091 386 : DWARFUnit *DWARFDebugLine::SectionParser::prepareToParse(uint32_t Offset) {
1092 : DWARFUnit *U = nullptr;
1093 386 : auto It = LineToUnit.find(Offset);
1094 386 : if (It != LineToUnit.end())
1095 295 : U = It->second;
1096 386 : DebugLineData.setAddressSize(U ? U->getAddressByteSize() : 0);
1097 386 : return U;
1098 : }
1099 :
1100 386 : void DWARFDebugLine::SectionParser::moveToNextTable(uint32_t OldOffset,
1101 : const Prologue &P) {
1102 : // If the length field is not valid, we don't know where the next table is, so
1103 : // cannot continue to parse. Mark the parser as done, and leave the Offset
1104 : // value as it currently is. This will be the end of the bad length field.
1105 386 : if (!P.totalLengthIsValid()) {
1106 6 : Done = true;
1107 6 : return;
1108 : }
1109 :
1110 380 : Offset = OldOffset + P.TotalLength + P.sizeofTotalLength();
1111 760 : if (!DebugLineData.isValidOffset(Offset)) {
1112 241 : Done = true;
1113 : }
1114 : }
|