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