1//===-- LVCodeViewReader.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// This implements the LVCodeViewReader class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
14#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
15#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
17#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
18#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
19#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
20#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
21#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
22#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
23#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
24#include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
25#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
26#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
27#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
28#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
29#include "llvm/Object/COFF.h"
30#include "llvm/Support/Errc.h"
31#include "llvm/Support/Error.h"
32#include "llvm/Support/FormatAdapters.h"
33#include "llvm/Support/FormatVariadic.h"
34#include "llvm/Support/WithColor.h"
35
36using namespace llvm;
37using namespace llvm::codeview;
38using namespace llvm::logicalview;
39using namespace llvm::msf;
40using namespace llvm::object;
41using namespace llvm::pdb;
42
43#define DEBUG_TYPE "CodeViewReader"
44
45StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {
46 switch (Kind) {
47#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
48 case EnumName: \
49 return #EnumName;
50#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
51 default:
52 return "UnknownSym";
53 }
54 llvm_unreachable("Unknown SymbolKind::Kind");
55}
56
57std::string LVCodeViewReader::formatRegisterId(RegisterId Register,
58 CPUType CPU) {
59#define RETURN_CASE(Enum, X, Ret) \
60 case Enum::X: \
61 return Ret;
62
63 if (CPU == CPUType::ARMNT) {
64 switch (Register) {
65#define CV_REGISTERS_ARM
66#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
67#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
68#undef CV_REGISTER
69#undef CV_REGISTERS_ARM
70
71 default:
72 break;
73 }
74 } else if (CPU == CPUType::ARM64) {
75 switch (Register) {
76#define CV_REGISTERS_ARM64
77#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
78#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
79#undef CV_REGISTER
80#undef CV_REGISTERS_ARM64
81
82 default:
83 break;
84 }
85 } else {
86 switch (Register) {
87#define CV_REGISTERS_X86
88#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
89#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
90#undef CV_REGISTER
91#undef CV_REGISTERS_X86
92
93 default:
94 break;
95 }
96 }
97 return "formatUnknownEnum(Id)";
98}
99
100void LVCodeViewReader::printRelocatedField(StringRef Label,
101 const coff_section *CoffSection,
102 uint32_t RelocOffset,
103 uint32_t Offset,
104 StringRef *RelocSym) {
105 StringRef SymStorage;
106 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
107 if (!resolveSymbolName(CoffSection, Offset: RelocOffset, Name&: Symbol))
108 W.printSymbolOffset(Label, Symbol, Value: Offset);
109 else
110 W.printHex(Label, Value: RelocOffset);
111}
112
113void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,
114 uint32_t RelocOffset, uint32_t Offset,
115 StringRef *RelocSym) {
116 StringRef SymStorage;
117 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
118 if (resolveSymbolName(CoffSection, Offset: RelocOffset, Name&: Symbol))
119 Symbol = "";
120}
121
122Expected<StringRef>
123LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
124 const SymbolGroup *SG) {
125 if (SG) {
126 Expected<StringRef> Filename = SG->getNameFromChecksums(Offset: FileOffset);
127 if (!Filename) {
128 consumeError(Err: Filename.takeError());
129 return StringRef("");
130 }
131 return *Filename;
132 }
133
134 // The file checksum subsection should precede all references to it.
135 if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
136 return createStringError(EC: object_error::parse_failed, S: getFileName());
137
138 VarStreamArray<FileChecksumEntry>::Iterator Iter =
139 CVFileChecksumTable.getArray().at(Offset: FileOffset);
140
141 // Check if the file checksum table offset is valid.
142 if (Iter == CVFileChecksumTable.end())
143 return createStringError(EC: object_error::parse_failed, S: getFileName());
144
145 Expected<StringRef> NameOrErr = CVStringTable.getString(Offset: Iter->FileNameOffset);
146 if (!NameOrErr)
147 return createStringError(EC: object_error::parse_failed, S: getFileName());
148 return *NameOrErr;
149}
150
151Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
152 uint32_t FileOffset,
153 const SymbolGroup *SG) {
154 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
155 if (!NameOrErr)
156 return NameOrErr.takeError();
157 W.printHex(Label, Str: *NameOrErr, Value: FileOffset);
158 return Error::success();
159}
160
161void LVCodeViewReader::cacheRelocations() {
162 for (const SectionRef &Section : getObj().sections()) {
163 const coff_section *CoffSection = getObj().getCOFFSection(Section);
164
165 auto &RM = RelocMap[CoffSection];
166 llvm::append_range(C&: RM, R: Section.relocations());
167
168 // Sort relocations by address.
169 llvm::sort(C&: RM, Comp: [](RelocationRef L, RelocationRef R) {
170 return L.getOffset() < R.getOffset();
171 });
172 }
173}
174
175// Given a section and an offset into this section the function returns the
176// symbol used for the relocation at the offset.
177Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
178 uint64_t Offset, SymbolRef &Sym) {
179 const auto &Relocations = RelocMap[CoffSection];
180 basic_symbol_iterator SymI = getObj().symbol_end();
181 for (const RelocationRef &Relocation : Relocations) {
182 uint64_t RelocationOffset = Relocation.getOffset();
183
184 if (RelocationOffset == Offset) {
185 SymI = Relocation.getSymbol();
186 break;
187 }
188 }
189 if (SymI == getObj().symbol_end())
190 return make_error<StringError>(Args: "Unknown Symbol", Args: inconvertibleErrorCode());
191 Sym = *SymI;
192 return ErrorSuccess();
193}
194
195// Given a section and an offset into this section the function returns the
196// name of the symbol used for the relocation at the offset.
197Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
198 uint64_t Offset, StringRef &Name) {
199 SymbolRef Symbol;
200 if (Error E = resolveSymbol(CoffSection, Offset, Sym&: Symbol))
201 return E;
202 Expected<StringRef> NameOrErr = Symbol.getName();
203 if (!NameOrErr)
204 return NameOrErr.takeError();
205 Name = *NameOrErr;
206 return ErrorSuccess();
207}
208
209// CodeView and DWARF can have references to compiler generated elements,
210// used for initialization. The MSVC includes in the PDBs, internal compile
211// units, associated with the MS runtime support. We mark them as 'system'
212// and they are printed only if the command line option 'internal=system'.
213bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {
214 Name = Name.empty() ? Element->getName() : Name;
215 auto Find = [=](const char *String) -> bool { return Name.contains(Other: String); };
216 auto Starts = [=](const char *Pattern) -> bool {
217 return Name.starts_with(Prefix: Pattern);
218 };
219 auto CheckExclude = [&]() -> bool {
220 if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
221 return true;
222 if (Find("_s__"))
223 return true;
224 if (Find("_CatchableType") || Find("_TypeDescriptor"))
225 return true;
226 if (Find("Intermediate\\vctools"))
227 return true;
228 if (Find("$initializer$") || Find("dynamic initializer"))
229 return true;
230 if (Find("`vftable'") || Find("_GLOBAL__sub"))
231 return true;
232 return false;
233 };
234 bool Excluded = CheckExclude();
235 if (Excluded)
236 Element->setIsSystem();
237
238 return Excluded;
239}
240
241Error LVCodeViewReader::collectInlineeInfo(
242 DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {
243 for (const InlineeSourceLine &Line : Lines) {
244 TypeIndex TIInlinee = Line.Header->Inlinee;
245 uint32_t LineNumber = Line.Header->SourceLineNum;
246 uint32_t FileOffset = Line.Header->FileID;
247 LLVM_DEBUG({
248 DictScope S(W, "InlineeSourceLine");
249 LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);
250 if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
251 return Err;
252 W.printNumber("SourceLineNum", LineNumber);
253
254 if (Lines.hasExtraFiles()) {
255 W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
256 ListScope ExtraFiles(W, "ExtraFiles");
257 for (const ulittle32_t &FID : Line.ExtraFiles)
258 if (Error Err = printFileNameForOffset("FileID", FID, SG))
259 return Err;
260 }
261 });
262 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
263 if (!NameOrErr)
264 return NameOrErr.takeError();
265 LogicalVisitor.addInlineeInfo(TI: TIInlinee, LineNumber, Filename: *NameOrErr);
266 }
267
268 return Error::success();
269}
270
271Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
272 BinaryStreamReader SR(Subsection, llvm::endianness::little);
273 DebugInlineeLinesSubsectionRef Lines;
274 if (Error E = Lines.initialize(Reader: SR))
275 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
276
277 return collectInlineeInfo(Lines);
278}
279
280Error LVCodeViewReader::createLines(
281 const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,
282 uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
283 const SymbolGroup *SG) {
284 LLVM_DEBUG({
285 uint32_t End = Begin + Size;
286 W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
287 });
288
289 for (const LineNumberEntry &Line : LineNumbers) {
290 if (Line.Offset >= Size)
291 return createStringError(EC: object_error::parse_failed, S: getFileName());
292
293 LineInfo LI(Line.Flags);
294
295 LLVM_DEBUG({
296 W.getOStream() << formatv(
297 "{0} {1:x-8}\n", utostr(LI.getStartLine()),
298 fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));
299 });
300
301 // The 'processLines()' function will move each created logical line
302 // to its enclosing logical scope, using the debug ranges information
303 // and they will be released when its scope parent is deleted.
304 LVLineDebug *LineDebug = createLineDebug();
305 CULines.push_back(Elt: LineDebug);
306 LVAddress Address = linearAddress(Segment, Offset: Begin + Line.Offset);
307 LineDebug->setAddress(Address + Addendum);
308
309 if (LI.isAlwaysStepInto())
310 LineDebug->setIsAlwaysStepInto();
311 else if (LI.isNeverStepInto())
312 LineDebug->setIsNeverStepInto();
313 else
314 LineDebug->setLineNumber(LI.getStartLine());
315
316 if (LI.isStatement())
317 LineDebug->setIsNewStatement();
318
319 Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset: NameIndex, SG);
320 if (!NameOrErr)
321 return NameOrErr.takeError();
322 LineDebug->setFilename(*NameOrErr);
323 }
324
325 return Error::success();
326}
327
328Error LVCodeViewReader::initializeFileAndStringTables(
329 BinaryStreamReader &Reader) {
330 while (Reader.bytesRemaining() > 0 &&
331 (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
332 // The section consists of a number of subsection in the following format:
333 // |SubSectionType|SubSectionSize|Contents...|
334 uint32_t SubType, SubSectionSize;
335
336 if (Error E = Reader.readInteger(Dest&: SubType))
337 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
338 if (Error E = Reader.readInteger(Dest&: SubSectionSize))
339 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
340
341 StringRef Contents;
342 if (Error E = Reader.readFixedString(Dest&: Contents, Length: SubSectionSize))
343 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
344
345 BinaryStreamRef ST(Contents, llvm::endianness::little);
346 switch (DebugSubsectionKind(SubType)) {
347 case DebugSubsectionKind::FileChecksums:
348 if (Error E = CVFileChecksumTable.initialize(Stream: ST))
349 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
350 break;
351 case DebugSubsectionKind::StringTable:
352 if (Error E = CVStringTable.initialize(Contents: ST))
353 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
354 break;
355 default:
356 break;
357 }
358
359 uint32_t PaddedSize = alignTo(Value: SubSectionSize, Align: 4);
360 if (Error E = Reader.skip(Amount: PaddedSize - SubSectionSize))
361 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
362 }
363
364 return Error::success();
365}
366
367Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {
368 LLVM_DEBUG({
369 W.printString("Guid", formatv("{0}", TS.getGuid()).str());
370 W.printNumber("Age", TS.getAge());
371 W.printString("Name", TS.getName());
372 });
373
374 SmallString<128> ServerName(TS.getName());
375 BuffOrErr = MemoryBuffer::getFile(Filename: ServerName);
376 if (BuffOrErr.getError()) {
377 // The server name does not exist. Try in the same directory as the
378 // input file.
379 ServerName = createAlternativePath(From: ServerName);
380 BuffOrErr = MemoryBuffer::getFile(Filename: ServerName);
381 if (BuffOrErr.getError()) {
382 // For the error message, use the original type server name.
383 return createStringError(EC: errc::bad_file_descriptor,
384 Fmt: "File '%s' does not exist.",
385 Vals: TS.getName().str().c_str());
386 }
387 }
388 MemBuffer = std::move(BuffOrErr.get());
389
390 // Check if the buffer corresponds to a PDB file.
391 assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&
392 "Invalid PDB file.");
393
394 if (Error Err = loadDataForPDB(Type: PDB_ReaderType::Native, Path: ServerName, Session))
395 return createStringError(EC: errorToErrorCode(Err: std::move(Err)), Fmt: "%s",
396 Vals: ServerName.c_str());
397
398 PdbSession.reset(p: static_cast<NativeSession *>(Session.release()));
399 PDBFile &Pdb = PdbSession->getPDBFile();
400
401 // Just because a file with a matching name was found and it was an actual
402 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
403 // must match the GUID specified in the TypeServer2 record.
404 Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
405 if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
406 return createStringError(EC: errc::invalid_argument, S: "signature_out_of_date");
407
408 // The reader needs to switch to a type server, to process the types from
409 // the server. We need to keep the original input source, as reading other
410 // sections will require the input associated with the loaded object file.
411 TypeServer = std::make_shared<InputFile>(args: &Pdb);
412 LogicalVisitor.setInput(TypeServer);
413
414 LazyRandomTypeCollection &Types = types();
415 LazyRandomTypeCollection &Ids = ids();
416 if (Error Err = traverseTypes(Pdb, Types, Ids))
417 return Err;
418
419 return Error::success();
420}
421
422Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,
423 CVTypeArray &CVTypesObj) {
424 LLVM_DEBUG({
425 W.printHex("Count", Precomp.getTypesCount());
426 W.printHex("Signature", Precomp.getSignature());
427 W.printString("PrecompFile", Precomp.getPrecompFilePath());
428 });
429
430 SmallString<128> ServerName(Precomp.getPrecompFilePath());
431 BuffOrErr = MemoryBuffer::getFile(Filename: ServerName);
432 if (BuffOrErr.getError()) {
433 // The server name does not exist. Try in the directory as the input file.
434 ServerName = createAlternativePath(From: ServerName);
435 if (BuffOrErr.getError()) {
436 // For the error message, use the original type server name.
437 return createStringError(EC: errc::bad_file_descriptor,
438 Fmt: "File '%s' does not exist.",
439 Vals: Precomp.getPrecompFilePath().str().c_str());
440 }
441 }
442 MemBuffer = std::move(BuffOrErr.get());
443
444 Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Source: *MemBuffer);
445 if (errorToErrorCode(Err: BinOrErr.takeError()))
446 return createStringError(EC: errc::not_supported,
447 Fmt: "Binary object format in '%s' is not supported.",
448 Vals: ServerName.c_str());
449
450 Binary &BinaryObj = *BinOrErr.get();
451 if (!BinaryObj.isCOFF())
452 return createStringError(EC: errc::not_supported, Fmt: "'%s' is not a COFF object.",
453 Vals: ServerName.c_str());
454
455 Builder = std::make_unique<AppendingTypeTableBuilder>(args&: BuilderAllocator);
456
457 // The MSVC precompiled header object file, should contain just a single
458 // ".debug$P" section.
459 COFFObjectFile &Obj = *cast<COFFObjectFile>(Val: &BinaryObj);
460 for (const SectionRef &Section : Obj.sections()) {
461 Expected<StringRef> SectionNameOrErr = Section.getName();
462 if (!SectionNameOrErr)
463 return SectionNameOrErr.takeError();
464 if (*SectionNameOrErr == ".debug$P") {
465 Expected<StringRef> DataOrErr = Section.getContents();
466 if (!DataOrErr)
467 return DataOrErr.takeError();
468 uint32_t Magic;
469 if (Error Err = consume(Data&: *DataOrErr, Item&: Magic))
470 return Err;
471 if (Magic != COFF::DEBUG_SECTION_MAGIC)
472 return errorCodeToError(EC: object_error::parse_failed);
473
474 ReaderPrecomp = std::make_unique<BinaryStreamReader>(
475 args&: *DataOrErr, args: llvm::endianness::little);
476 cantFail(
477 Err: ReaderPrecomp->readArray(Array&: CVTypesPrecomp, Size: ReaderPrecomp->getLength()));
478
479 // Append all the type records up to the LF_ENDPRECOMP marker and
480 // check if the signatures match.
481 for (const CVType &Type : CVTypesPrecomp) {
482 ArrayRef<uint8_t> TypeData = Type.data();
483 if (Type.kind() == LF_ENDPRECOMP) {
484 EndPrecompRecord EndPrecomp = cantFail(
485 ValOrErr: TypeDeserializer::deserializeAs<EndPrecompRecord>(Data: TypeData));
486 if (Precomp.getSignature() != EndPrecomp.getSignature())
487 return createStringError(EC: errc::invalid_argument, S: "no matching pch");
488 break;
489 }
490 Builder->insertRecordBytes(Record&: TypeData);
491 }
492 // Done processing .debug$P, break out of section loop.
493 break;
494 }
495 }
496
497 // Append all the type records, skipping the first record which is the
498 // reference to the precompiled header object information.
499 for (const CVType &Type : CVTypesObj) {
500 ArrayRef<uint8_t> TypeData = Type.data();
501 if (Type.kind() != LF_PRECOMP)
502 Builder->insertRecordBytes(Record&: TypeData);
503 }
504
505 // Set up a type stream that refers to the added type records.
506 Builder->ForEachRecord(
507 Func: [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(x: Type); });
508
509 ItemStream =
510 std::make_unique<BinaryItemStream<CVType>>(args: llvm::endianness::little);
511 ItemStream->setItems(TypeArray);
512 TypeStream.setUnderlyingStream(NewStream: *ItemStream);
513
514 PrecompHeader =
515 std::make_shared<LazyRandomTypeCollection>(args&: TypeStream, args: TypeArray.size());
516
517 // Change the original input source to use the collected type records.
518 LogicalVisitor.setInput(PrecompHeader);
519
520 LazyRandomTypeCollection &Types = types();
521 LazyRandomTypeCollection &Ids = ids();
522 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
523 LogicalVisitor.getShared());
524 return visitTypeStream(Types, Callbacks&: TDV);
525}
526
527Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
528 const SectionRef &Section) {
529 LLVM_DEBUG({
530 ListScope D(W, "CodeViewTypes");
531 W.printNumber("Section", SectionName, getObj().getSectionID(Section));
532 });
533
534 Expected<StringRef> DataOrErr = Section.getContents();
535 if (!DataOrErr)
536 return DataOrErr.takeError();
537 uint32_t Magic;
538 if (Error Err = consume(Data&: *DataOrErr, Item&: Magic))
539 return Err;
540 if (Magic != COFF::DEBUG_SECTION_MAGIC)
541 return errorCodeToError(EC: object_error::parse_failed);
542
543 // Get the first type record. It will indicate if this object uses a type
544 // server (/Zi) or a PCH file (/Yu).
545 CVTypeArray CVTypes;
546 BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);
547 cantFail(Err: Reader.readArray(Array&: CVTypes, Size: Reader.getLength()));
548 CVTypeArray::Iterator FirstType = CVTypes.begin();
549
550 // The object was compiled with /Zi. It uses types from a type server PDB.
551 if (FirstType->kind() == LF_TYPESERVER2) {
552 TypeServer2Record TS = cantFail(
553 ValOrErr: TypeDeserializer::deserializeAs<TypeServer2Record>(Data: FirstType->data()));
554 return loadTypeServer(TS);
555 }
556
557 // The object was compiled with /Yc or /Yu. It uses types from another
558 // object file with a matching signature.
559 if (FirstType->kind() == LF_PRECOMP) {
560 PrecompRecord Precomp = cantFail(
561 ValOrErr: TypeDeserializer::deserializeAs<PrecompRecord>(Data: FirstType->data()));
562 return loadPrecompiledObject(Precomp, CVTypesObj&: CVTypes);
563 }
564
565 LazyRandomTypeCollection &Types = types();
566 LazyRandomTypeCollection &Ids = ids();
567 Types.reset(Data: *DataOrErr, RecordCountHint: 100);
568 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
569 LogicalVisitor.getShared());
570 return visitTypeStream(Types, Callbacks&: TDV);
571}
572
573Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
574 LazyRandomTypeCollection &Types,
575 LazyRandomTypeCollection &Ids) {
576 // Traverse types (TPI and IPI).
577 auto VisitTypes = [&](LazyRandomTypeCollection &Types,
578 LazyRandomTypeCollection &Ids,
579 SpecialStream StreamIdx) -> Error {
580 LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
581 LogicalVisitor.getShared());
582 return visitTypeStream(Types, Callbacks&: TDV);
583 };
584
585 Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
586 if (!StreamTpiOrErr)
587 return StreamTpiOrErr.takeError();
588 TpiStream &StreamTpi = *StreamTpiOrErr;
589 StreamTpi.buildHashMap();
590 LLVM_DEBUG({
591 W.getOStream() << formatv("Showing {0:N} TPI records\n",
592 StreamTpi.getNumTypeRecords());
593 });
594 if (Error Err = VisitTypes(Types, Ids, StreamTPI))
595 return Err;
596
597 Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
598 if (!StreamIpiOrErr)
599 return StreamIpiOrErr.takeError();
600 TpiStream &StreamIpi = *StreamIpiOrErr;
601 StreamIpi.buildHashMap();
602 LLVM_DEBUG({
603 W.getOStream() << formatv("Showing {0:N} IPI records\n",
604 StreamIpi.getNumTypeRecords());
605 });
606 return VisitTypes(Ids, Ids, StreamIPI);
607}
608
609Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
610 const SectionRef &Section,
611 StringRef SectionContents) {
612 ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
613 Subsection.bytes_end());
614 LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),
615 SectionContents);
616 CVSymbolArray Symbols;
617 BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
618 if (Error E = Reader.readArray(Array&: Symbols, Size: Reader.getLength()))
619 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
620
621 LazyRandomTypeCollection &Types = types();
622 LazyRandomTypeCollection &Ids = ids();
623 SymbolVisitorCallbackPipeline Pipeline;
624 SymbolDeserializer Deserializer(&VisitorDelegate,
625 CodeViewContainer::ObjectFile);
626 // As we are processing a COFF format, use TPI as IPI, so the generic code
627 // to process the CodeView format does not contain any additional checks.
628 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
629 &VisitorDelegate, LogicalVisitor.getShared());
630
631 Pipeline.addCallbackToPipeline(Callbacks&: Deserializer);
632 Pipeline.addCallbackToPipeline(Callbacks&: Traverser);
633 CVSymbolVisitor Visitor(Pipeline);
634 return Visitor.visitSymbolStream(Symbols);
635}
636
637Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
638 const SectionRef &Section) {
639 LLVM_DEBUG({
640 ListScope D(W, "CodeViewDebugInfo");
641 W.printNumber("Section", SectionName, getObj().getSectionID(Section));
642 });
643
644 Expected<StringRef> SectionOrErr = Section.getContents();
645 if (!SectionOrErr)
646 return SectionOrErr.takeError();
647 StringRef SectionContents = *SectionOrErr;
648 StringRef Data = SectionContents;
649
650 SmallVector<StringRef, 10> SymbolNames;
651 StringMap<StringRef> FunctionLineTables;
652
653 uint32_t Magic;
654 if (Error E = consume(Data, Item&: Magic))
655 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
656
657 if (Magic != COFF::DEBUG_SECTION_MAGIC)
658 return createStringError(EC: object_error::parse_failed, S: getFileName());
659
660 BinaryStreamReader FSReader(Data, llvm::endianness::little);
661 if (Error Err = initializeFileAndStringTables(Reader&: FSReader))
662 return Err;
663
664 while (!Data.empty()) {
665 // The section consists of a number of subsection in the following format:
666 // |SubSectionType|SubSectionSize|Contents...|
667 uint32_t SubType, SubSectionSize;
668 if (Error E = consume(Data, Item&: SubType))
669 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
670 if (Error E = consume(Data, Item&: SubSectionSize))
671 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
672
673 // Process the subsection as normal even if the ignore bit is set.
674 SubType &= ~SubsectionIgnoreFlag;
675
676 // Get the contents of the subsection.
677 if (SubSectionSize > Data.size())
678 return createStringError(EC: object_error::parse_failed, S: getFileName());
679 StringRef Contents = Data.substr(Start: 0, N: SubSectionSize);
680
681 // Add SubSectionSize to the current offset and align that offset
682 // to find the next subsection.
683 size_t SectionOffset = Data.data() - SectionContents.data();
684 size_t NextOffset = SectionOffset + SubSectionSize;
685 NextOffset = alignTo(Value: NextOffset, Align: 4);
686 if (NextOffset > SectionContents.size())
687 return createStringError(EC: object_error::parse_failed, S: getFileName());
688 Data = SectionContents.drop_front(N: NextOffset);
689
690 switch (DebugSubsectionKind(SubType)) {
691 case DebugSubsectionKind::Symbols:
692 if (Error Err =
693 traverseSymbolsSubsection(Subsection: Contents, Section, SectionContents))
694 return Err;
695 break;
696
697 case DebugSubsectionKind::InlineeLines:
698 if (Error Err = traverseInlineeLines(Subsection: Contents))
699 return Err;
700 break;
701
702 case DebugSubsectionKind::Lines:
703 // Holds a PC to file:line table. Some data to parse this subsection
704 // is stored in the other subsections, so just check sanity and store
705 // the pointers for deferred processing.
706
707 // Collect function and ranges only if we need to print logical lines.
708 if (options().getGeneralCollectRanges()) {
709
710 if (SubSectionSize < 12) {
711 // There should be at least three words to store two function
712 // relocations and size of the code.
713 return createStringError(EC: object_error::parse_failed, S: getFileName());
714 }
715
716 StringRef SymbolName;
717 if (Error Err = resolveSymbolName(CoffSection: getObj().getCOFFSection(Section),
718 Offset: SectionOffset, Name&: SymbolName))
719 return createStringError(EC: errorToErrorCode(Err: std::move(Err)),
720 S: getFileName());
721
722 LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
723 if (!FunctionLineTables.try_emplace(Key: SymbolName, Args&: Contents).second) {
724 // Saw debug info for this function already?
725 return createStringError(EC: object_error::parse_failed, S: getFileName());
726 }
727
728 SymbolNames.push_back(Elt: SymbolName);
729 }
730 break;
731
732 // Do nothing for unrecognized subsections.
733 default:
734 break;
735 }
736 W.flush();
737 }
738
739 // Traverse the line tables now that we've read all the subsections and
740 // know all the required information.
741 for (StringRef SymbolName : SymbolNames) {
742 LLVM_DEBUG({
743 ListScope S(W, "FunctionLineTable");
744 W.printString("Symbol Name", SymbolName);
745 });
746
747 BinaryStreamReader Reader(FunctionLineTables[SymbolName],
748 llvm::endianness::little);
749
750 DebugLinesSubsectionRef Lines;
751 if (Error E = Lines.initialize(Reader))
752 return createStringError(EC: errorToErrorCode(Err: std::move(E)), S: getFileName());
753
754 // Find the associated symbol table information.
755 LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(Name: SymbolName);
756 LVScope *Function = SymbolTableEntry.Scope;
757 if (!Function)
758 continue;
759
760 LVAddress Addendum = SymbolTableEntry.Address;
761 LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;
762
763 // The given scope represents the function that contains the line numbers.
764 // Collect all generated debug lines associated with the function.
765 CULines.clear();
766
767 // For the given scope, collect all scopes ranges.
768 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
769 ScopesWithRanges->clear();
770 Function->getRanges(RangeList&: *ScopesWithRanges);
771 ScopesWithRanges->sort();
772
773 uint16_t Segment = Lines.header()->RelocSegment;
774 uint32_t Begin = Lines.header()->RelocOffset;
775 uint32_t Size = Lines.header()->CodeSize;
776 for (const LineColumnEntry &Block : Lines)
777 if (Error Err = createLines(LineNumbers: Block.LineNumbers, Addendum, Segment, Begin,
778 Size, NameIndex: Block.NameIndex))
779 return Err;
780
781 // Include lines from any inlined functions within the current function.
782 includeInlineeLines(SectionIndex, Function);
783
784 if (Error Err = createInstructions(Function, SectionIndex))
785 return Err;
786
787 processLines(DebugLines: &CULines, SectionIndex, Function);
788 }
789
790 return Error::success();
791}
792
793void LVCodeViewReader::sortScopes() { Root->sort(); }
794
795void LVCodeViewReader::print(raw_ostream &OS) const {
796 LLVM_DEBUG(dbgs() << "CreateReaders\n");
797}
798
799void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
800 const SectionRef &Section,
801 bool IsComdat) {
802 if (!Obj.isCOFF())
803 return;
804
805 const COFFObjectFile *Object = cast<COFFObjectFile>(Val: &Obj);
806
807 for (const SymbolRef &Sym : Object->symbols()) {
808 if (!Section.containsSymbol(S: Sym))
809 continue;
810
811 COFFSymbolRef Symbol = Object->getCOFFSymbol(Symbol: Sym);
812 if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)
813 continue;
814
815 StringRef SymbolName;
816 Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);
817 if (!SymNameOrErr) {
818 W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
819 << "\n";
820 consumeError(Err: SymNameOrErr.takeError());
821 continue;
822 }
823 SymbolName = *SymNameOrErr;
824
825 LLVM_DEBUG({
826 Expected<const coff_section *> SectionOrErr =
827 Object->getSection(Symbol.getSectionNumber());
828 if (!SectionOrErr) {
829 W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
830 << "\n";
831 consumeError(SectionOrErr.takeError());
832 return;
833 }
834 W.printNumber("Section #", Symbol.getSectionNumber());
835 W.printString("Name", SymbolName);
836 W.printHex("Value", Symbol.getValue());
837 });
838
839 // Record the symbol name (linkage) and its loading address.
840 addToSymbolTable(Name: SymbolName, Address: Symbol.getValue(), SectionIndex: Symbol.getSectionNumber(),
841 IsComdat);
842 }
843}
844
845Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {
846 if (Error Err = loadTargetInfo(Obj))
847 return Err;
848
849 // Initialization required when processing a COFF file:
850 // Cache the symbols relocations.
851 // Create a mapping for virtual addresses.
852 // Get the functions entry points.
853 cacheRelocations();
854 mapVirtualAddress(COFFObj: Obj);
855
856 for (const SectionRef &Section : Obj.sections()) {
857 Expected<StringRef> SectionNameOrErr = Section.getName();
858 if (!SectionNameOrErr)
859 return SectionNameOrErr.takeError();
860 // .debug$T is a standard CodeView type section, while .debug$P is the
861 // same format but used for MSVC precompiled header object files.
862 if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
863 if (Error Err = traverseTypeSection(SectionName: *SectionNameOrErr, Section))
864 return Err;
865 }
866
867 // Process collected namespaces.
868 LogicalVisitor.processNamespaces();
869
870 for (const SectionRef &Section : Obj.sections()) {
871 Expected<StringRef> SectionNameOrErr = Section.getName();
872 if (!SectionNameOrErr)
873 return SectionNameOrErr.takeError();
874 if (*SectionNameOrErr == ".debug$S")
875 if (Error Err = traverseSymbolSection(SectionName: *SectionNameOrErr, Section))
876 return Err;
877 }
878
879 // Check if we have to close the Compile Unit scope.
880 LogicalVisitor.closeScope();
881
882 // Traverse the strings recorded and transform them into filenames.
883 LogicalVisitor.processFiles();
884
885 // Process collected element lines.
886 LogicalVisitor.processLines();
887
888 // Translate composite names into a single component.
889 Root->transformScopedName();
890 return Error::success();
891}
892
893Error LVCodeViewReader::createScopes(PDBFile &Pdb) {
894 if (Error Err = loadTargetInfo(Pdb))
895 return Err;
896
897 if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())
898 return Error::success();
899
900 // Open the executable associated with the PDB file and get the section
901 // addresses used to calculate linear addresses for CodeView Symbols.
902 if (!ExePath.empty()) {
903 ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
904 MemoryBuffer::getFileOrSTDIN(Filename: ExePath);
905 if (BuffOrErr.getError()) {
906 return createStringError(EC: errc::bad_file_descriptor,
907 Fmt: "File '%s' does not exist.", Vals: ExePath.c_str());
908 }
909 BinaryBuffer = std::move(BuffOrErr.get());
910
911 // Check if the buffer corresponds to a PECOFF executable.
912 assert(identify_magic(BinaryBuffer->getBuffer()) ==
913 file_magic::pecoff_executable &&
914 "Invalid PECOFF executable file.");
915
916 Expected<std::unique_ptr<Binary>> BinOrErr =
917 createBinary(Source: BinaryBuffer->getMemBufferRef());
918 if (errorToErrorCode(Err: BinOrErr.takeError())) {
919 return createStringError(EC: errc::not_supported,
920 Fmt: "Binary object format in '%s' is not supported.",
921 Vals: ExePath.c_str());
922 }
923 BinaryExecutable = std::move(*BinOrErr);
924 if (COFFObjectFile *COFFObject =
925 dyn_cast<COFFObjectFile>(Val: BinaryExecutable.get()))
926 mapVirtualAddress(COFFObj: *COFFObject);
927 }
928
929 // In order to generate a full logical view, we have to traverse both
930 // streams TPI and IPI if they are present. The following table gives
931 // the stream where a specified type is located. If the IPI stream is
932 // not present, all the types are located in the TPI stream.
933 //
934 // TPI Stream:
935 // LF_POINTER LF_MODIFIER LF_PROCEDURE LF_MFUNCTION
936 // LF_LABEL LF_ARGLIST LF_FIELDLIST LF_ARRAY
937 // LF_CLASS LF_STRUCTURE LF_INTERFACE LF_UNION
938 // LF_ENUM LF_TYPESERVER2 LF_VFTABLE LF_VTSHAPE
939 // LF_BITFIELD LF_METHODLIST LF_PRECOMP LF_ENDPRECOMP
940 //
941 // IPI stream:
942 // LF_FUNC_ID LF_MFUNC_ID LF_BUILDINFO
943 // LF_SUBSTR_LIST LF_STRING_ID LF_UDT_SRC_LINE
944 // LF_UDT_MOD_SRC_LINE
945
946 LazyRandomTypeCollection &Types = types();
947 LazyRandomTypeCollection &Ids = ids();
948 if (Error Err = traverseTypes(Pdb, Types, Ids))
949 return Err;
950
951 // Process collected namespaces.
952 LogicalVisitor.processNamespaces();
953
954 LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });
955
956 auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
957 DebugInlineeLinesSubsectionRef &Lines) -> Error {
958 return collectInlineeInfo(Lines, SG: &SG);
959 };
960
961 FilterOptions Filters = {};
962 LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);
963 const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);
964 if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
965 File&: Input, HeaderScope, Callback: VisitInlineeLines))
966 return Err;
967
968 // Traverse global symbols.
969 LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
970 if (Pdb.hasPDBGlobalsStream()) {
971 Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
972 if (!GlobalsOrErr)
973 return GlobalsOrErr.takeError();
974 GlobalsStream &Globals = *GlobalsOrErr;
975 const GSIHashTable &Table = Globals.getGlobalsTable();
976 Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
977 if (ExpectedSyms) {
978
979 SymbolVisitorCallbackPipeline Pipeline;
980 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
981 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
982 LogicalVisitor.getShared());
983
984 // As the global symbols do not have an associated Compile Unit, create
985 // one, as the container for all global symbols.
986 RecordPrefix Prefix(SymbolKind::S_COMPILE3);
987 CVSymbol Symbol(&Prefix, sizeof(Prefix));
988 uint32_t Offset = 0;
989 if (Error Err = Traverser.visitSymbolBegin(Record&: Symbol, Offset))
990 consumeError(Err: std::move(Err));
991 else {
992 // The CodeView compile unit containing the global symbols does not
993 // have a name; generate one using its parent name (object filename)
994 // follow by the '_global' string.
995 std::string Name(CompileUnit->getParentScope()->getName());
996 CompileUnit->setName(Name.append(s: "_global"));
997
998 Pipeline.addCallbackToPipeline(Callbacks&: Deserializer);
999 Pipeline.addCallbackToPipeline(Callbacks&: Traverser);
1000 CVSymbolVisitor Visitor(Pipeline);
1001
1002 BinaryStreamRef SymStream =
1003 ExpectedSyms->getSymbolArray().getUnderlyingStream();
1004 for (uint32_t PubSymOff : Table) {
1005 Expected<CVSymbol> Sym = readSymbolFromStream(Stream: SymStream, Offset: PubSymOff);
1006 if (Sym) {
1007 if (Error Err = Visitor.visitSymbolRecord(Record&: *Sym, Offset: PubSymOff))
1008 return createStringError(EC: errorToErrorCode(Err: std::move(Err)),
1009 S: getFileName());
1010 } else {
1011 consumeError(Err: Sym.takeError());
1012 }
1013 }
1014 }
1015
1016 LogicalVisitor.closeScope();
1017 } else {
1018 consumeError(Err: ExpectedSyms.takeError());
1019 }
1020 }
1021
1022 // Traverse symbols (DBI).
1023 LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });
1024
1025 auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
1026 Expected<ModuleDebugStreamRef> ExpectedModS =
1027 getModuleDebugStream(File&: Pdb, Index: Modi);
1028 if (ExpectedModS) {
1029 ModuleDebugStreamRef &ModS = *ExpectedModS;
1030
1031 LLVM_DEBUG({
1032 W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
1033 });
1034
1035 SymbolVisitorCallbackPipeline Pipeline;
1036 SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
1037 LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
1038 LogicalVisitor.getShared());
1039
1040 Pipeline.addCallbackToPipeline(Callbacks&: Deserializer);
1041 Pipeline.addCallbackToPipeline(Callbacks&: Traverser);
1042 CVSymbolVisitor Visitor(Pipeline);
1043 BinarySubstreamRef SS = ModS.getSymbolsSubstream();
1044 if (Error Err =
1045 Visitor.visitSymbolStream(Symbols: ModS.getSymbolArray(), InitialOffset: SS.Offset))
1046 return createStringError(EC: errorToErrorCode(Err: std::move(Err)),
1047 S: getFileName());
1048 } else {
1049 // If the module stream does not exist, it is not an error condition.
1050 consumeError(Err: ExpectedModS.takeError());
1051 }
1052
1053 return Error::success();
1054 };
1055
1056 if (Error Err = iterateSymbolGroups(Input, HeaderScope, Callback: VisitSymbolGroup))
1057 return Err;
1058
1059 // At this stage, the logical view contains all scopes, symbols and types.
1060 // For PDBs we can use the module id, to access its specific compile unit.
1061 // The line record addresses has been already resolved, so we can apply the
1062 // flow as when processing DWARF.
1063
1064 LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });
1065
1066 // Record all line records for a Compile Unit.
1067 CULines.clear();
1068
1069 auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
1070 DebugLinesSubsectionRef &Lines) -> Error {
1071 if (!options().getPrintLines())
1072 return Error::success();
1073
1074 uint16_t Segment = Lines.header()->RelocSegment;
1075 uint32_t Begin = Lines.header()->RelocOffset;
1076 uint32_t Size = Lines.header()->CodeSize;
1077
1078 LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });
1079
1080 // We have line information for a new module; finish processing the
1081 // collected information for the current module. Once it is done, start
1082 // recording the line information for the new module.
1083 if (CurrentModule != Modi) {
1084 if (Error Err = processModule())
1085 return Err;
1086 CULines.clear();
1087 CurrentModule = Modi;
1088 }
1089
1090 for (const LineColumnEntry &Block : Lines)
1091 if (Error Err = createLines(LineNumbers: Block.LineNumbers, /*Addendum=*/0, Segment,
1092 Begin, Size, NameIndex: Block.NameIndex, SG: &SG))
1093 return Err;
1094
1095 return Error::success();
1096 };
1097
1098 if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
1099 File&: Input, HeaderScope, Callback: VisitDebugLines))
1100 return Err;
1101
1102 // Check if we have to close the Compile Unit scope.
1103 LogicalVisitor.closeScope();
1104
1105 // Process collected element lines.
1106 LogicalVisitor.processLines();
1107
1108 // Translate composite names into a single component.
1109 Root->transformScopedName();
1110 return Error::success();
1111}
1112
1113Error LVCodeViewReader::processModule() {
1114 if (LVScope *Scope = getScopeForModule(Modi: CurrentModule)) {
1115 CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
1116
1117 LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });
1118
1119 // For the given compile unit, collect all scopes ranges.
1120 // For a complete ranges and lines mapping, the logical view support
1121 // needs for the compile unit to have a low and high pc values. We
1122 // can traverse the 'Modules' section and get the information for the
1123 // specific module. Another option, is from all the ranges collected
1124 // to take the first and last values.
1125 LVSectionIndex SectionIndex = DotTextSectionIndex;
1126 LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
1127 ScopesWithRanges->clear();
1128 CompileUnit->getRanges(RangeList&: *ScopesWithRanges);
1129 if (!ScopesWithRanges->empty())
1130 CompileUnit->addObject(LowerAddress: ScopesWithRanges->getLower(),
1131 UpperAddress: ScopesWithRanges->getUpper());
1132 ScopesWithRanges->sort();
1133
1134 if (Error Err = createInstructions())
1135 return Err;
1136
1137 // Include lines from any inlined functions within the current function.
1138 includeInlineeLines(SectionIndex, Function: Scope);
1139
1140 processLines(DebugLines: &CULines, SectionIndex, Function: nullptr);
1141 }
1142
1143 return Error::success();
1144}
1145
1146// In order to create the scopes, the CodeView Reader will:
1147// = Traverse the TPI/IPI stream (Type visitor):
1148// Collect forward references, scoped names, type indexes that will represent
1149// a logical element, strings, line records, linkage names.
1150// = Traverse the symbols section (Symbol visitor):
1151// Create the scopes tree and creates the required logical elements, by
1152// using the collected indexes from the type visitor.
1153Error LVCodeViewReader::createScopes() {
1154 LLVM_DEBUG({
1155 W.startLine() << "\n";
1156 W.printString("File", getFileName().str());
1157 W.printString("Exe", ExePath);
1158 W.printString("Format", FileFormatName);
1159 });
1160
1161 if (Error Err = LVReader::createScopes())
1162 return Err;
1163
1164 LogicalVisitor.setRoot(Root);
1165
1166 if (isObj()) {
1167 if (Error Err = createScopes(Obj&: getObj()))
1168 return Err;
1169 } else {
1170 if (Error Err = createScopes(Pdb&: getPdb()))
1171 return Err;
1172 }
1173
1174 return Error::success();
1175}
1176
1177Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
1178 // Detect the architecture from the object file. We usually don't need OS
1179 // info to lookup a target and create register info.
1180 Triple TT;
1181 TT.setArch(Kind: Triple::ArchType(Obj.getArch()));
1182 TT.setVendor(Triple::UnknownVendor);
1183 TT.setOS(Triple::UnknownOS);
1184
1185 // Features to be passed to target/subtarget
1186 Expected<SubtargetFeatures> Features = Obj.getFeatures();
1187 SubtargetFeatures FeaturesValue;
1188 if (!Features) {
1189 consumeError(Err: Features.takeError());
1190 FeaturesValue = SubtargetFeatures();
1191 }
1192 FeaturesValue = *Features;
1193 return loadGenericTargetInfo(TheTriple: TT.str(), TheFeatures: FeaturesValue.getString());
1194}
1195
1196Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
1197 Triple TT;
1198 TT.setArch(Kind: Triple::ArchType::x86_64);
1199 TT.setVendor(Triple::UnknownVendor);
1200 TT.setOS(Triple::Win32);
1201
1202 StringRef TheFeature = "";
1203
1204 return loadGenericTargetInfo(TheTriple: TT.str(), TheFeatures: TheFeature);
1205}
1206
1207std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,
1208 ArrayRef<uint64_t> Operands) {
1209 // Get Compilation Unit CPU Type.
1210 CPUType CPU = getCompileUnitCPUType();
1211 // For CodeView the register always is in Operands[0];
1212 RegisterId Register = (RegisterId(Operands[0]));
1213 return formatRegisterId(Register, CPU);
1214}
1215