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