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