106c3fb27SDimitry Andric //===-- LVCodeViewReader.cpp ----------------------------------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric // This implements the LVCodeViewReader class.
1006c3fb27SDimitry Andric //
1106c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1206c3fb27SDimitry Andric
1306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
1406c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
1506c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
1606c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/EnumTables.h"
1706c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
1806c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
1906c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
2006c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
2106c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
2206c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
2306c3fb27SDimitry Andric #include "llvm/DebugInfo/LogicalView/Core/LVType.h"
2406c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/GenericError.h"
2506c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
2606c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
2706c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
2806c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
2906c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
3006c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
3106c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
3206c3fb27SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
3306c3fb27SDimitry Andric #include "llvm/Demangle/Demangle.h"
3406c3fb27SDimitry Andric #include "llvm/Object/COFF.h"
3506c3fb27SDimitry Andric #include "llvm/Support/Errc.h"
3606c3fb27SDimitry Andric #include "llvm/Support/Error.h"
3706c3fb27SDimitry Andric #include "llvm/Support/FormatAdapters.h"
3806c3fb27SDimitry Andric #include "llvm/Support/FormatVariadic.h"
3906c3fb27SDimitry Andric #include "llvm/Support/WithColor.h"
4006c3fb27SDimitry Andric
4106c3fb27SDimitry Andric using namespace llvm;
4206c3fb27SDimitry Andric using namespace llvm::codeview;
4306c3fb27SDimitry Andric using namespace llvm::logicalview;
4406c3fb27SDimitry Andric using namespace llvm::msf;
4506c3fb27SDimitry Andric using namespace llvm::object;
4606c3fb27SDimitry Andric using namespace llvm::pdb;
4706c3fb27SDimitry Andric
4806c3fb27SDimitry Andric #define DEBUG_TYPE "CodeViewReader"
4906c3fb27SDimitry Andric
getSymbolKindName(SymbolKind Kind)5006c3fb27SDimitry Andric StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {
5106c3fb27SDimitry Andric switch (Kind) {
5206c3fb27SDimitry Andric #define SYMBOL_RECORD(EnumName, EnumVal, Name) \
5306c3fb27SDimitry Andric case EnumName: \
5406c3fb27SDimitry Andric return #EnumName;
5506c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
5606c3fb27SDimitry Andric default:
5706c3fb27SDimitry Andric return "UnknownSym";
5806c3fb27SDimitry Andric }
5906c3fb27SDimitry Andric llvm_unreachable("Unknown SymbolKind::Kind");
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric
formatRegisterId(RegisterId Register,CPUType CPU)6206c3fb27SDimitry Andric std::string LVCodeViewReader::formatRegisterId(RegisterId Register,
6306c3fb27SDimitry Andric CPUType CPU) {
6406c3fb27SDimitry Andric #define RETURN_CASE(Enum, X, Ret) \
6506c3fb27SDimitry Andric case Enum::X: \
6606c3fb27SDimitry Andric return Ret;
6706c3fb27SDimitry Andric
6806c3fb27SDimitry Andric if (CPU == CPUType::ARMNT) {
6906c3fb27SDimitry Andric switch (Register) {
7006c3fb27SDimitry Andric #define CV_REGISTERS_ARM
7106c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
7206c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
7306c3fb27SDimitry Andric #undef CV_REGISTER
7406c3fb27SDimitry Andric #undef CV_REGISTERS_ARM
7506c3fb27SDimitry Andric
7606c3fb27SDimitry Andric default:
7706c3fb27SDimitry Andric break;
7806c3fb27SDimitry Andric }
7906c3fb27SDimitry Andric } else if (CPU == CPUType::ARM64) {
8006c3fb27SDimitry Andric switch (Register) {
8106c3fb27SDimitry Andric #define CV_REGISTERS_ARM64
8206c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
8306c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
8406c3fb27SDimitry Andric #undef CV_REGISTER
8506c3fb27SDimitry Andric #undef CV_REGISTERS_ARM64
8606c3fb27SDimitry Andric
8706c3fb27SDimitry Andric default:
8806c3fb27SDimitry Andric break;
8906c3fb27SDimitry Andric }
9006c3fb27SDimitry Andric } else {
9106c3fb27SDimitry Andric switch (Register) {
9206c3fb27SDimitry Andric #define CV_REGISTERS_X86
9306c3fb27SDimitry Andric #define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
9406c3fb27SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
9506c3fb27SDimitry Andric #undef CV_REGISTER
9606c3fb27SDimitry Andric #undef CV_REGISTERS_X86
9706c3fb27SDimitry Andric
9806c3fb27SDimitry Andric default:
9906c3fb27SDimitry Andric break;
10006c3fb27SDimitry Andric }
10106c3fb27SDimitry Andric }
10206c3fb27SDimitry Andric return "formatUnknownEnum(Id)";
10306c3fb27SDimitry Andric }
10406c3fb27SDimitry Andric
printRelocatedField(StringRef Label,const coff_section * CoffSection,uint32_t RelocOffset,uint32_t Offset,StringRef * RelocSym)10506c3fb27SDimitry Andric void LVCodeViewReader::printRelocatedField(StringRef Label,
10606c3fb27SDimitry Andric const coff_section *CoffSection,
10706c3fb27SDimitry Andric uint32_t RelocOffset,
10806c3fb27SDimitry Andric uint32_t Offset,
10906c3fb27SDimitry Andric StringRef *RelocSym) {
11006c3fb27SDimitry Andric StringRef SymStorage;
11106c3fb27SDimitry Andric StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
11206c3fb27SDimitry Andric if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
11306c3fb27SDimitry Andric W.printSymbolOffset(Label, Symbol, Offset);
11406c3fb27SDimitry Andric else
11506c3fb27SDimitry Andric W.printHex(Label, RelocOffset);
11606c3fb27SDimitry Andric }
11706c3fb27SDimitry Andric
getLinkageName(const coff_section * CoffSection,uint32_t RelocOffset,uint32_t Offset,StringRef * RelocSym)11806c3fb27SDimitry Andric void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,
11906c3fb27SDimitry Andric uint32_t RelocOffset, uint32_t Offset,
12006c3fb27SDimitry Andric StringRef *RelocSym) {
12106c3fb27SDimitry Andric StringRef SymStorage;
12206c3fb27SDimitry Andric StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
12306c3fb27SDimitry Andric if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
12406c3fb27SDimitry Andric Symbol = "";
12506c3fb27SDimitry Andric }
12606c3fb27SDimitry Andric
12706c3fb27SDimitry Andric Expected<StringRef>
getFileNameForFileOffset(uint32_t FileOffset,const SymbolGroup * SG)12806c3fb27SDimitry Andric LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
12906c3fb27SDimitry Andric const SymbolGroup *SG) {
13006c3fb27SDimitry Andric if (SG) {
13106c3fb27SDimitry Andric Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset);
13206c3fb27SDimitry Andric if (!Filename) {
13306c3fb27SDimitry Andric consumeError(Filename.takeError());
13406c3fb27SDimitry Andric return StringRef("");
13506c3fb27SDimitry Andric }
13606c3fb27SDimitry Andric return *Filename;
13706c3fb27SDimitry Andric }
13806c3fb27SDimitry Andric
13906c3fb27SDimitry Andric // The file checksum subsection should precede all references to it.
14006c3fb27SDimitry Andric if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
14106c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
14206c3fb27SDimitry Andric
14306c3fb27SDimitry Andric VarStreamArray<FileChecksumEntry>::Iterator Iter =
14406c3fb27SDimitry Andric CVFileChecksumTable.getArray().at(FileOffset);
14506c3fb27SDimitry Andric
14606c3fb27SDimitry Andric // Check if the file checksum table offset is valid.
14706c3fb27SDimitry Andric if (Iter == CVFileChecksumTable.end())
14806c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
14906c3fb27SDimitry Andric
15006c3fb27SDimitry Andric Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset);
15106c3fb27SDimitry Andric if (!NameOrErr)
15206c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
15306c3fb27SDimitry Andric return *NameOrErr;
15406c3fb27SDimitry Andric }
15506c3fb27SDimitry Andric
printFileNameForOffset(StringRef Label,uint32_t FileOffset,const SymbolGroup * SG)15606c3fb27SDimitry Andric Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
15706c3fb27SDimitry Andric uint32_t FileOffset,
15806c3fb27SDimitry Andric const SymbolGroup *SG) {
15906c3fb27SDimitry Andric Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
16006c3fb27SDimitry Andric if (!NameOrErr)
16106c3fb27SDimitry Andric return NameOrErr.takeError();
16206c3fb27SDimitry Andric W.printHex(Label, *NameOrErr, FileOffset);
16306c3fb27SDimitry Andric return Error::success();
16406c3fb27SDimitry Andric }
16506c3fb27SDimitry Andric
cacheRelocations()16606c3fb27SDimitry Andric void LVCodeViewReader::cacheRelocations() {
16706c3fb27SDimitry Andric for (const SectionRef &Section : getObj().sections()) {
16806c3fb27SDimitry Andric const coff_section *CoffSection = getObj().getCOFFSection(Section);
16906c3fb27SDimitry Andric
17006c3fb27SDimitry Andric for (const RelocationRef &Relocacion : Section.relocations())
17106c3fb27SDimitry Andric RelocMap[CoffSection].push_back(Relocacion);
17206c3fb27SDimitry Andric
17306c3fb27SDimitry Andric // Sort relocations by address.
17406c3fb27SDimitry Andric llvm::sort(RelocMap[CoffSection], [](RelocationRef L, RelocationRef R) {
17506c3fb27SDimitry Andric return L.getOffset() < R.getOffset();
17606c3fb27SDimitry Andric });
17706c3fb27SDimitry Andric }
17806c3fb27SDimitry Andric }
17906c3fb27SDimitry Andric
18006c3fb27SDimitry Andric // Given a section and an offset into this section the function returns the
18106c3fb27SDimitry Andric // symbol used for the relocation at the offset.
resolveSymbol(const coff_section * CoffSection,uint64_t Offset,SymbolRef & Sym)18206c3fb27SDimitry Andric Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
18306c3fb27SDimitry Andric uint64_t Offset, SymbolRef &Sym) {
18406c3fb27SDimitry Andric const auto &Relocations = RelocMap[CoffSection];
18506c3fb27SDimitry Andric basic_symbol_iterator SymI = getObj().symbol_end();
18606c3fb27SDimitry Andric for (const RelocationRef &Relocation : Relocations) {
18706c3fb27SDimitry Andric uint64_t RelocationOffset = Relocation.getOffset();
18806c3fb27SDimitry Andric
18906c3fb27SDimitry Andric if (RelocationOffset == Offset) {
19006c3fb27SDimitry Andric SymI = Relocation.getSymbol();
19106c3fb27SDimitry Andric break;
19206c3fb27SDimitry Andric }
19306c3fb27SDimitry Andric }
19406c3fb27SDimitry Andric if (SymI == getObj().symbol_end())
19506c3fb27SDimitry Andric return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode());
19606c3fb27SDimitry Andric Sym = *SymI;
19706c3fb27SDimitry Andric return ErrorSuccess();
19806c3fb27SDimitry Andric }
19906c3fb27SDimitry Andric
20006c3fb27SDimitry Andric // Given a section and an offset into this section the function returns the
20106c3fb27SDimitry Andric // name of the symbol used for the relocation at the offset.
resolveSymbolName(const coff_section * CoffSection,uint64_t Offset,StringRef & Name)20206c3fb27SDimitry Andric Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
20306c3fb27SDimitry Andric uint64_t Offset, StringRef &Name) {
20406c3fb27SDimitry Andric SymbolRef Symbol;
20506c3fb27SDimitry Andric if (Error E = resolveSymbol(CoffSection, Offset, Symbol))
20606c3fb27SDimitry Andric return E;
20706c3fb27SDimitry Andric Expected<StringRef> NameOrErr = Symbol.getName();
20806c3fb27SDimitry Andric if (!NameOrErr)
20906c3fb27SDimitry Andric return NameOrErr.takeError();
21006c3fb27SDimitry Andric Name = *NameOrErr;
21106c3fb27SDimitry Andric return ErrorSuccess();
21206c3fb27SDimitry Andric }
21306c3fb27SDimitry Andric
21406c3fb27SDimitry Andric // CodeView and DWARF can have references to compiler generated elements,
21506c3fb27SDimitry Andric // used for initialization. The MSVC includes in the PDBs, internal compile
21606c3fb27SDimitry Andric // units, associated with the MS runtime support. We mark them as 'system'
21706c3fb27SDimitry Andric // and they are printed only if the command line option 'internal=system'.
isSystemEntry(LVElement * Element,StringRef Name) const21806c3fb27SDimitry Andric bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {
21906c3fb27SDimitry Andric Name = Name.empty() ? Element->getName() : Name;
220*7a6dacacSDimitry Andric auto Find = [=](const char *String) -> bool { return Name.contains(String); };
22106c3fb27SDimitry Andric auto Starts = [=](const char *Pattern) -> bool {
2225f757f3fSDimitry Andric return Name.starts_with(Pattern);
22306c3fb27SDimitry Andric };
22406c3fb27SDimitry Andric auto CheckExclude = [&]() -> bool {
22506c3fb27SDimitry Andric if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
22606c3fb27SDimitry Andric return true;
22706c3fb27SDimitry Andric if (Find("_s__"))
22806c3fb27SDimitry Andric return true;
22906c3fb27SDimitry Andric if (Find("_CatchableType") || Find("_TypeDescriptor"))
23006c3fb27SDimitry Andric return true;
23106c3fb27SDimitry Andric if (Find("Intermediate\\vctools"))
23206c3fb27SDimitry Andric return true;
23306c3fb27SDimitry Andric if (Find("$initializer$") || Find("dynamic initializer"))
23406c3fb27SDimitry Andric return true;
23506c3fb27SDimitry Andric if (Find("`vftable'") || Find("_GLOBAL__sub"))
23606c3fb27SDimitry Andric return true;
23706c3fb27SDimitry Andric return false;
23806c3fb27SDimitry Andric };
23906c3fb27SDimitry Andric bool Excluded = CheckExclude();
24006c3fb27SDimitry Andric if (Excluded)
24106c3fb27SDimitry Andric Element->setIsSystem();
24206c3fb27SDimitry Andric
24306c3fb27SDimitry Andric return Excluded;
24406c3fb27SDimitry Andric }
24506c3fb27SDimitry Andric
collectInlineeInfo(DebugInlineeLinesSubsectionRef & Lines,const llvm::pdb::SymbolGroup * SG)24606c3fb27SDimitry Andric Error LVCodeViewReader::collectInlineeInfo(
24706c3fb27SDimitry Andric DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {
24806c3fb27SDimitry Andric for (const InlineeSourceLine &Line : Lines) {
24906c3fb27SDimitry Andric TypeIndex TIInlinee = Line.Header->Inlinee;
25006c3fb27SDimitry Andric uint32_t LineNumber = Line.Header->SourceLineNum;
25106c3fb27SDimitry Andric uint32_t FileOffset = Line.Header->FileID;
25206c3fb27SDimitry Andric LLVM_DEBUG({
25306c3fb27SDimitry Andric DictScope S(W, "InlineeSourceLine");
25406c3fb27SDimitry Andric LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);
25506c3fb27SDimitry Andric if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
25606c3fb27SDimitry Andric return Err;
25706c3fb27SDimitry Andric W.printNumber("SourceLineNum", LineNumber);
25806c3fb27SDimitry Andric
25906c3fb27SDimitry Andric if (Lines.hasExtraFiles()) {
26006c3fb27SDimitry Andric W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
26106c3fb27SDimitry Andric ListScope ExtraFiles(W, "ExtraFiles");
26206c3fb27SDimitry Andric for (const ulittle32_t &FID : Line.ExtraFiles)
26306c3fb27SDimitry Andric if (Error Err = printFileNameForOffset("FileID", FID, SG))
26406c3fb27SDimitry Andric return Err;
26506c3fb27SDimitry Andric }
26606c3fb27SDimitry Andric });
26706c3fb27SDimitry Andric Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
26806c3fb27SDimitry Andric if (!NameOrErr)
26906c3fb27SDimitry Andric return NameOrErr.takeError();
27006c3fb27SDimitry Andric LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);
27106c3fb27SDimitry Andric }
27206c3fb27SDimitry Andric
27306c3fb27SDimitry Andric return Error::success();
27406c3fb27SDimitry Andric }
27506c3fb27SDimitry Andric
traverseInlineeLines(StringRef Subsection)27606c3fb27SDimitry Andric Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
2775f757f3fSDimitry Andric BinaryStreamReader SR(Subsection, llvm::endianness::little);
27806c3fb27SDimitry Andric DebugInlineeLinesSubsectionRef Lines;
27906c3fb27SDimitry Andric if (Error E = Lines.initialize(SR))
28006c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
28106c3fb27SDimitry Andric
28206c3fb27SDimitry Andric return collectInlineeInfo(Lines);
28306c3fb27SDimitry Andric }
28406c3fb27SDimitry Andric
createLines(const FixedStreamArray<LineNumberEntry> & LineNumbers,LVAddress Addendum,uint32_t Segment,uint32_t Begin,uint32_t Size,uint32_t NameIndex,const SymbolGroup * SG)28506c3fb27SDimitry Andric Error LVCodeViewReader::createLines(
28606c3fb27SDimitry Andric const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,
28706c3fb27SDimitry Andric uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
28806c3fb27SDimitry Andric const SymbolGroup *SG) {
28906c3fb27SDimitry Andric LLVM_DEBUG({
29006c3fb27SDimitry Andric uint32_t End = Begin + Size;
29106c3fb27SDimitry Andric W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
29206c3fb27SDimitry Andric });
29306c3fb27SDimitry Andric
29406c3fb27SDimitry Andric for (const LineNumberEntry &Line : LineNumbers) {
29506c3fb27SDimitry Andric if (Line.Offset >= Size)
29606c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
29706c3fb27SDimitry Andric
29806c3fb27SDimitry Andric LineInfo LI(Line.Flags);
29906c3fb27SDimitry Andric
30006c3fb27SDimitry Andric LLVM_DEBUG({
30106c3fb27SDimitry Andric W.getOStream() << formatv(
30206c3fb27SDimitry Andric "{0} {1:x-8}\n", utostr(LI.getStartLine()),
30306c3fb27SDimitry Andric fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));
30406c3fb27SDimitry Andric });
30506c3fb27SDimitry Andric
30606c3fb27SDimitry Andric // The 'processLines()' function will move each created logical line
30706c3fb27SDimitry Andric // to its enclosing logical scope, using the debug ranges information
30806c3fb27SDimitry Andric // and they will be released when its scope parent is deleted.
30906c3fb27SDimitry Andric LVLineDebug *LineDebug = createLineDebug();
31006c3fb27SDimitry Andric CULines.push_back(LineDebug);
31106c3fb27SDimitry Andric LVAddress Address = linearAddress(Segment, Begin + Line.Offset);
31206c3fb27SDimitry Andric LineDebug->setAddress(Address + Addendum);
31306c3fb27SDimitry Andric
31406c3fb27SDimitry Andric if (LI.isAlwaysStepInto())
31506c3fb27SDimitry Andric LineDebug->setIsAlwaysStepInto();
31606c3fb27SDimitry Andric else if (LI.isNeverStepInto())
31706c3fb27SDimitry Andric LineDebug->setIsNeverStepInto();
31806c3fb27SDimitry Andric else
31906c3fb27SDimitry Andric LineDebug->setLineNumber(LI.getStartLine());
32006c3fb27SDimitry Andric
32106c3fb27SDimitry Andric if (LI.isStatement())
32206c3fb27SDimitry Andric LineDebug->setIsNewStatement();
32306c3fb27SDimitry Andric
32406c3fb27SDimitry Andric Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);
32506c3fb27SDimitry Andric if (!NameOrErr)
32606c3fb27SDimitry Andric return NameOrErr.takeError();
32706c3fb27SDimitry Andric LineDebug->setFilename(*NameOrErr);
32806c3fb27SDimitry Andric }
32906c3fb27SDimitry Andric
33006c3fb27SDimitry Andric return Error::success();
33106c3fb27SDimitry Andric }
33206c3fb27SDimitry Andric
initializeFileAndStringTables(BinaryStreamReader & Reader)33306c3fb27SDimitry Andric Error LVCodeViewReader::initializeFileAndStringTables(
33406c3fb27SDimitry Andric BinaryStreamReader &Reader) {
33506c3fb27SDimitry Andric while (Reader.bytesRemaining() > 0 &&
33606c3fb27SDimitry Andric (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
33706c3fb27SDimitry Andric // The section consists of a number of subsection in the following format:
33806c3fb27SDimitry Andric // |SubSectionType|SubSectionSize|Contents...|
33906c3fb27SDimitry Andric uint32_t SubType, SubSectionSize;
34006c3fb27SDimitry Andric
34106c3fb27SDimitry Andric if (Error E = Reader.readInteger(SubType))
34206c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
34306c3fb27SDimitry Andric if (Error E = Reader.readInteger(SubSectionSize))
34406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
34506c3fb27SDimitry Andric
34606c3fb27SDimitry Andric StringRef Contents;
34706c3fb27SDimitry Andric if (Error E = Reader.readFixedString(Contents, SubSectionSize))
34806c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
34906c3fb27SDimitry Andric
3505f757f3fSDimitry Andric BinaryStreamRef ST(Contents, llvm::endianness::little);
35106c3fb27SDimitry Andric switch (DebugSubsectionKind(SubType)) {
35206c3fb27SDimitry Andric case DebugSubsectionKind::FileChecksums:
35306c3fb27SDimitry Andric if (Error E = CVFileChecksumTable.initialize(ST))
35406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
35506c3fb27SDimitry Andric break;
35606c3fb27SDimitry Andric case DebugSubsectionKind::StringTable:
35706c3fb27SDimitry Andric if (Error E = CVStringTable.initialize(ST))
35806c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
35906c3fb27SDimitry Andric break;
36006c3fb27SDimitry Andric default:
36106c3fb27SDimitry Andric break;
36206c3fb27SDimitry Andric }
36306c3fb27SDimitry Andric
36406c3fb27SDimitry Andric uint32_t PaddedSize = alignTo(SubSectionSize, 4);
36506c3fb27SDimitry Andric if (Error E = Reader.skip(PaddedSize - SubSectionSize))
36606c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
36706c3fb27SDimitry Andric }
36806c3fb27SDimitry Andric
36906c3fb27SDimitry Andric return Error::success();
37006c3fb27SDimitry Andric }
37106c3fb27SDimitry Andric
loadTypeServer(TypeServer2Record & TS)37206c3fb27SDimitry Andric Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {
37306c3fb27SDimitry Andric LLVM_DEBUG({
37406c3fb27SDimitry Andric W.printString("Guid", formatv("{0}", TS.getGuid()).str());
37506c3fb27SDimitry Andric W.printNumber("Age", TS.getAge());
37606c3fb27SDimitry Andric W.printString("Name", TS.getName());
37706c3fb27SDimitry Andric });
37806c3fb27SDimitry Andric
37906c3fb27SDimitry Andric SmallString<128> ServerName(TS.getName());
38006c3fb27SDimitry Andric BuffOrErr = MemoryBuffer::getFile(ServerName);
38106c3fb27SDimitry Andric if (BuffOrErr.getError()) {
38206c3fb27SDimitry Andric // The server name does not exist. Try in the same directory as the
38306c3fb27SDimitry Andric // input file.
38406c3fb27SDimitry Andric ServerName = createAlternativePath(ServerName);
38506c3fb27SDimitry Andric BuffOrErr = MemoryBuffer::getFile(ServerName);
38606c3fb27SDimitry Andric if (BuffOrErr.getError()) {
38706c3fb27SDimitry Andric // For the error message, use the original type server name.
38806c3fb27SDimitry Andric return createStringError(errc::bad_file_descriptor,
38906c3fb27SDimitry Andric "File '%s' does not exist.",
39006c3fb27SDimitry Andric TS.getName().str().c_str());
39106c3fb27SDimitry Andric }
39206c3fb27SDimitry Andric }
39306c3fb27SDimitry Andric MemBuffer = std::move(BuffOrErr.get());
39406c3fb27SDimitry Andric
39506c3fb27SDimitry Andric // Check if the buffer corresponds to a PDB file.
39606c3fb27SDimitry Andric assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&
39706c3fb27SDimitry Andric "Invalid PDB file.");
39806c3fb27SDimitry Andric
39906c3fb27SDimitry Andric if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))
40006c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(Err)), "%s",
40106c3fb27SDimitry Andric ServerName.c_str());
40206c3fb27SDimitry Andric
40306c3fb27SDimitry Andric PdbSession.reset(static_cast<NativeSession *>(Session.release()));
40406c3fb27SDimitry Andric PDBFile &Pdb = PdbSession->getPDBFile();
40506c3fb27SDimitry Andric
40606c3fb27SDimitry Andric // Just because a file with a matching name was found and it was an actual
40706c3fb27SDimitry Andric // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
40806c3fb27SDimitry Andric // must match the GUID specified in the TypeServer2 record.
40906c3fb27SDimitry Andric Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
41006c3fb27SDimitry Andric if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
41106c3fb27SDimitry Andric return createStringError(errc::invalid_argument, "signature_out_of_date");
41206c3fb27SDimitry Andric
41306c3fb27SDimitry Andric // The reader needs to switch to a type server, to process the types from
41406c3fb27SDimitry Andric // the server. We need to keep the original input source, as reading other
41506c3fb27SDimitry Andric // sections will require the input associated with the loaded object file.
41606c3fb27SDimitry Andric TypeServer = std::make_shared<InputFile>(&Pdb);
41706c3fb27SDimitry Andric LogicalVisitor.setInput(TypeServer);
41806c3fb27SDimitry Andric
41906c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types();
42006c3fb27SDimitry Andric LazyRandomTypeCollection &Ids = ids();
42106c3fb27SDimitry Andric if (Error Err = traverseTypes(Pdb, Types, Ids))
42206c3fb27SDimitry Andric return Err;
42306c3fb27SDimitry Andric
42406c3fb27SDimitry Andric return Error::success();
42506c3fb27SDimitry Andric }
42606c3fb27SDimitry Andric
loadPrecompiledObject(PrecompRecord & Precomp,CVTypeArray & CVTypesObj)42706c3fb27SDimitry Andric Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,
42806c3fb27SDimitry Andric CVTypeArray &CVTypesObj) {
42906c3fb27SDimitry Andric LLVM_DEBUG({
43006c3fb27SDimitry Andric W.printHex("Count", Precomp.getTypesCount());
43106c3fb27SDimitry Andric W.printHex("Signature", Precomp.getSignature());
43206c3fb27SDimitry Andric W.printString("PrecompFile", Precomp.getPrecompFilePath());
43306c3fb27SDimitry Andric });
43406c3fb27SDimitry Andric
43506c3fb27SDimitry Andric SmallString<128> ServerName(Precomp.getPrecompFilePath());
43606c3fb27SDimitry Andric BuffOrErr = MemoryBuffer::getFile(ServerName);
43706c3fb27SDimitry Andric if (BuffOrErr.getError()) {
43806c3fb27SDimitry Andric // The server name does not exist. Try in the directory as the input file.
43906c3fb27SDimitry Andric ServerName = createAlternativePath(ServerName);
44006c3fb27SDimitry Andric if (BuffOrErr.getError()) {
44106c3fb27SDimitry Andric // For the error message, use the original type server name.
44206c3fb27SDimitry Andric return createStringError(errc::bad_file_descriptor,
44306c3fb27SDimitry Andric "File '%s' does not exist.",
44406c3fb27SDimitry Andric Precomp.getPrecompFilePath().str().c_str());
44506c3fb27SDimitry Andric }
44606c3fb27SDimitry Andric }
44706c3fb27SDimitry Andric MemBuffer = std::move(BuffOrErr.get());
44806c3fb27SDimitry Andric
44906c3fb27SDimitry Andric Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer);
45006c3fb27SDimitry Andric if (errorToErrorCode(BinOrErr.takeError()))
45106c3fb27SDimitry Andric return createStringError(errc::not_supported,
45206c3fb27SDimitry Andric "Binary object format in '%s' is not supported.",
45306c3fb27SDimitry Andric ServerName.c_str());
45406c3fb27SDimitry Andric
45506c3fb27SDimitry Andric Binary &BinaryObj = *BinOrErr.get();
45606c3fb27SDimitry Andric if (!BinaryObj.isCOFF())
45706c3fb27SDimitry Andric return createStringError(errc::not_supported, "'%s' is not a COFF object.",
45806c3fb27SDimitry Andric ServerName.c_str());
45906c3fb27SDimitry Andric
46006c3fb27SDimitry Andric Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);
46106c3fb27SDimitry Andric
46206c3fb27SDimitry Andric // The MSVC precompiled header object file, should contain just a single
46306c3fb27SDimitry Andric // ".debug$P" section.
46406c3fb27SDimitry Andric COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj);
46506c3fb27SDimitry Andric for (const SectionRef &Section : Obj.sections()) {
46606c3fb27SDimitry Andric Expected<StringRef> SectionNameOrErr = Section.getName();
46706c3fb27SDimitry Andric if (!SectionNameOrErr)
46806c3fb27SDimitry Andric return SectionNameOrErr.takeError();
46906c3fb27SDimitry Andric if (*SectionNameOrErr == ".debug$P") {
47006c3fb27SDimitry Andric Expected<StringRef> DataOrErr = Section.getContents();
47106c3fb27SDimitry Andric if (!DataOrErr)
47206c3fb27SDimitry Andric return DataOrErr.takeError();
47306c3fb27SDimitry Andric uint32_t Magic;
47406c3fb27SDimitry Andric if (Error Err = consume(*DataOrErr, Magic))
47506c3fb27SDimitry Andric return Err;
47606c3fb27SDimitry Andric if (Magic != COFF::DEBUG_SECTION_MAGIC)
47706c3fb27SDimitry Andric return errorCodeToError(object_error::parse_failed);
47806c3fb27SDimitry Andric
4795f757f3fSDimitry Andric ReaderPrecomp = std::make_unique<BinaryStreamReader>(
4805f757f3fSDimitry Andric *DataOrErr, llvm::endianness::little);
48106c3fb27SDimitry Andric cantFail(
48206c3fb27SDimitry Andric ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));
48306c3fb27SDimitry Andric
48406c3fb27SDimitry Andric // Append all the type records up to the LF_ENDPRECOMP marker and
48506c3fb27SDimitry Andric // check if the signatures match.
48606c3fb27SDimitry Andric for (const CVType &Type : CVTypesPrecomp) {
48706c3fb27SDimitry Andric ArrayRef<uint8_t> TypeData = Type.data();
48806c3fb27SDimitry Andric if (Type.kind() == LF_ENDPRECOMP) {
48906c3fb27SDimitry Andric EndPrecompRecord EndPrecomp = cantFail(
49006c3fb27SDimitry Andric TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
49106c3fb27SDimitry Andric if (Precomp.getSignature() != EndPrecomp.getSignature())
49206c3fb27SDimitry Andric return createStringError(errc::invalid_argument, "no matching pch");
49306c3fb27SDimitry Andric break;
49406c3fb27SDimitry Andric }
49506c3fb27SDimitry Andric Builder->insertRecordBytes(TypeData);
49606c3fb27SDimitry Andric }
49706c3fb27SDimitry Andric // Done processing .debug$P, break out of section loop.
49806c3fb27SDimitry Andric break;
49906c3fb27SDimitry Andric }
50006c3fb27SDimitry Andric }
50106c3fb27SDimitry Andric
50206c3fb27SDimitry Andric // Append all the type records, skipping the first record which is the
50306c3fb27SDimitry Andric // reference to the precompiled header object information.
50406c3fb27SDimitry Andric for (const CVType &Type : CVTypesObj) {
50506c3fb27SDimitry Andric ArrayRef<uint8_t> TypeData = Type.data();
50606c3fb27SDimitry Andric if (Type.kind() != LF_PRECOMP)
50706c3fb27SDimitry Andric Builder->insertRecordBytes(TypeData);
50806c3fb27SDimitry Andric }
50906c3fb27SDimitry Andric
51006c3fb27SDimitry Andric // Set up a type stream that refers to the added type records.
51106c3fb27SDimitry Andric Builder->ForEachRecord(
51206c3fb27SDimitry Andric [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });
51306c3fb27SDimitry Andric
51406c3fb27SDimitry Andric ItemStream =
5155f757f3fSDimitry Andric std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little);
51606c3fb27SDimitry Andric ItemStream->setItems(TypeArray);
51706c3fb27SDimitry Andric TypeStream.setUnderlyingStream(*ItemStream);
51806c3fb27SDimitry Andric
51906c3fb27SDimitry Andric PrecompHeader =
52006c3fb27SDimitry Andric std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());
52106c3fb27SDimitry Andric
52206c3fb27SDimitry Andric // Change the original input source to use the collected type records.
52306c3fb27SDimitry Andric LogicalVisitor.setInput(PrecompHeader);
52406c3fb27SDimitry Andric
52506c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types();
52606c3fb27SDimitry Andric LazyRandomTypeCollection &Ids = ids();
52706c3fb27SDimitry Andric LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
52806c3fb27SDimitry Andric LogicalVisitor.getShared());
52906c3fb27SDimitry Andric return visitTypeStream(Types, TDV);
53006c3fb27SDimitry Andric }
53106c3fb27SDimitry Andric
traverseTypeSection(StringRef SectionName,const SectionRef & Section)53206c3fb27SDimitry Andric Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
53306c3fb27SDimitry Andric const SectionRef &Section) {
53406c3fb27SDimitry Andric LLVM_DEBUG({
53506c3fb27SDimitry Andric ListScope D(W, "CodeViewTypes");
53606c3fb27SDimitry Andric W.printNumber("Section", SectionName, getObj().getSectionID(Section));
53706c3fb27SDimitry Andric });
53806c3fb27SDimitry Andric
53906c3fb27SDimitry Andric Expected<StringRef> DataOrErr = Section.getContents();
54006c3fb27SDimitry Andric if (!DataOrErr)
54106c3fb27SDimitry Andric return DataOrErr.takeError();
54206c3fb27SDimitry Andric uint32_t Magic;
54306c3fb27SDimitry Andric if (Error Err = consume(*DataOrErr, Magic))
54406c3fb27SDimitry Andric return Err;
54506c3fb27SDimitry Andric if (Magic != COFF::DEBUG_SECTION_MAGIC)
54606c3fb27SDimitry Andric return errorCodeToError(object_error::parse_failed);
54706c3fb27SDimitry Andric
54806c3fb27SDimitry Andric // Get the first type record. It will indicate if this object uses a type
54906c3fb27SDimitry Andric // server (/Zi) or a PCH file (/Yu).
55006c3fb27SDimitry Andric CVTypeArray CVTypes;
5515f757f3fSDimitry Andric BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);
55206c3fb27SDimitry Andric cantFail(Reader.readArray(CVTypes, Reader.getLength()));
55306c3fb27SDimitry Andric CVTypeArray::Iterator FirstType = CVTypes.begin();
55406c3fb27SDimitry Andric
55506c3fb27SDimitry Andric // The object was compiled with /Zi. It uses types from a type server PDB.
55606c3fb27SDimitry Andric if (FirstType->kind() == LF_TYPESERVER2) {
55706c3fb27SDimitry Andric TypeServer2Record TS = cantFail(
55806c3fb27SDimitry Andric TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
55906c3fb27SDimitry Andric return loadTypeServer(TS);
56006c3fb27SDimitry Andric }
56106c3fb27SDimitry Andric
56206c3fb27SDimitry Andric // The object was compiled with /Yc or /Yu. It uses types from another
56306c3fb27SDimitry Andric // object file with a matching signature.
56406c3fb27SDimitry Andric if (FirstType->kind() == LF_PRECOMP) {
56506c3fb27SDimitry Andric PrecompRecord Precomp = cantFail(
56606c3fb27SDimitry Andric TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
56706c3fb27SDimitry Andric return loadPrecompiledObject(Precomp, CVTypes);
56806c3fb27SDimitry Andric }
56906c3fb27SDimitry Andric
57006c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types();
57106c3fb27SDimitry Andric LazyRandomTypeCollection &Ids = ids();
57206c3fb27SDimitry Andric Types.reset(*DataOrErr, 100);
57306c3fb27SDimitry Andric LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
57406c3fb27SDimitry Andric LogicalVisitor.getShared());
57506c3fb27SDimitry Andric return visitTypeStream(Types, TDV);
57606c3fb27SDimitry Andric }
57706c3fb27SDimitry Andric
traverseTypes(PDBFile & Pdb,LazyRandomTypeCollection & Types,LazyRandomTypeCollection & Ids)57806c3fb27SDimitry Andric Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
57906c3fb27SDimitry Andric LazyRandomTypeCollection &Types,
58006c3fb27SDimitry Andric LazyRandomTypeCollection &Ids) {
58106c3fb27SDimitry Andric // Traverse types (TPI and IPI).
58206c3fb27SDimitry Andric auto VisitTypes = [&](LazyRandomTypeCollection &Types,
58306c3fb27SDimitry Andric LazyRandomTypeCollection &Ids,
58406c3fb27SDimitry Andric SpecialStream StreamIdx) -> Error {
58506c3fb27SDimitry Andric LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
58606c3fb27SDimitry Andric LogicalVisitor.getShared());
58706c3fb27SDimitry Andric return visitTypeStream(Types, TDV);
58806c3fb27SDimitry Andric };
58906c3fb27SDimitry Andric
59006c3fb27SDimitry Andric Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
59106c3fb27SDimitry Andric if (!StreamTpiOrErr)
59206c3fb27SDimitry Andric return StreamTpiOrErr.takeError();
59306c3fb27SDimitry Andric TpiStream &StreamTpi = *StreamTpiOrErr;
59406c3fb27SDimitry Andric StreamTpi.buildHashMap();
59506c3fb27SDimitry Andric LLVM_DEBUG({
59606c3fb27SDimitry Andric W.getOStream() << formatv("Showing {0:N} TPI records\n",
59706c3fb27SDimitry Andric StreamTpi.getNumTypeRecords());
59806c3fb27SDimitry Andric });
59906c3fb27SDimitry Andric if (Error Err = VisitTypes(Types, Ids, StreamTPI))
60006c3fb27SDimitry Andric return Err;
60106c3fb27SDimitry Andric
60206c3fb27SDimitry Andric Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
60306c3fb27SDimitry Andric if (!StreamIpiOrErr)
60406c3fb27SDimitry Andric return StreamIpiOrErr.takeError();
60506c3fb27SDimitry Andric TpiStream &StreamIpi = *StreamIpiOrErr;
60606c3fb27SDimitry Andric StreamIpi.buildHashMap();
60706c3fb27SDimitry Andric LLVM_DEBUG({
60806c3fb27SDimitry Andric W.getOStream() << formatv("Showing {0:N} IPI records\n",
60906c3fb27SDimitry Andric StreamIpi.getNumTypeRecords());
61006c3fb27SDimitry Andric });
61106c3fb27SDimitry Andric return VisitTypes(Ids, Ids, StreamIPI);
61206c3fb27SDimitry Andric }
61306c3fb27SDimitry Andric
traverseSymbolsSubsection(StringRef Subsection,const SectionRef & Section,StringRef SectionContents)61406c3fb27SDimitry Andric Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
61506c3fb27SDimitry Andric const SectionRef &Section,
61606c3fb27SDimitry Andric StringRef SectionContents) {
61706c3fb27SDimitry Andric ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
61806c3fb27SDimitry Andric Subsection.bytes_end());
61906c3fb27SDimitry Andric LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),
62006c3fb27SDimitry Andric SectionContents);
62106c3fb27SDimitry Andric CVSymbolArray Symbols;
6225f757f3fSDimitry Andric BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
62306c3fb27SDimitry Andric if (Error E = Reader.readArray(Symbols, Reader.getLength()))
62406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
62506c3fb27SDimitry Andric
62606c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types();
62706c3fb27SDimitry Andric LazyRandomTypeCollection &Ids = ids();
62806c3fb27SDimitry Andric SymbolVisitorCallbackPipeline Pipeline;
62906c3fb27SDimitry Andric SymbolDeserializer Deserializer(&VisitorDelegate,
63006c3fb27SDimitry Andric CodeViewContainer::ObjectFile);
63106c3fb27SDimitry Andric // As we are processing a COFF format, use TPI as IPI, so the generic code
63206c3fb27SDimitry Andric // to process the CodeView format does not contain any additional checks.
63306c3fb27SDimitry Andric LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
63406c3fb27SDimitry Andric &VisitorDelegate, LogicalVisitor.getShared());
63506c3fb27SDimitry Andric
63606c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Deserializer);
63706c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Traverser);
63806c3fb27SDimitry Andric CVSymbolVisitor Visitor(Pipeline);
63906c3fb27SDimitry Andric return Visitor.visitSymbolStream(Symbols);
64006c3fb27SDimitry Andric }
64106c3fb27SDimitry Andric
traverseSymbolSection(StringRef SectionName,const SectionRef & Section)64206c3fb27SDimitry Andric Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
64306c3fb27SDimitry Andric const SectionRef &Section) {
64406c3fb27SDimitry Andric LLVM_DEBUG({
64506c3fb27SDimitry Andric ListScope D(W, "CodeViewDebugInfo");
64606c3fb27SDimitry Andric W.printNumber("Section", SectionName, getObj().getSectionID(Section));
64706c3fb27SDimitry Andric });
64806c3fb27SDimitry Andric
64906c3fb27SDimitry Andric Expected<StringRef> SectionOrErr = Section.getContents();
65006c3fb27SDimitry Andric if (!SectionOrErr)
65106c3fb27SDimitry Andric return SectionOrErr.takeError();
65206c3fb27SDimitry Andric StringRef SectionContents = *SectionOrErr;
65306c3fb27SDimitry Andric StringRef Data = SectionContents;
65406c3fb27SDimitry Andric
65506c3fb27SDimitry Andric SmallVector<StringRef, 10> SymbolNames;
65606c3fb27SDimitry Andric StringMap<StringRef> FunctionLineTables;
65706c3fb27SDimitry Andric
65806c3fb27SDimitry Andric uint32_t Magic;
65906c3fb27SDimitry Andric if (Error E = consume(Data, Magic))
66006c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
66106c3fb27SDimitry Andric
66206c3fb27SDimitry Andric if (Magic != COFF::DEBUG_SECTION_MAGIC)
66306c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
66406c3fb27SDimitry Andric
6655f757f3fSDimitry Andric BinaryStreamReader FSReader(Data, llvm::endianness::little);
66606c3fb27SDimitry Andric if (Error Err = initializeFileAndStringTables(FSReader))
66706c3fb27SDimitry Andric return Err;
66806c3fb27SDimitry Andric
66906c3fb27SDimitry Andric while (!Data.empty()) {
67006c3fb27SDimitry Andric // The section consists of a number of subsection in the following format:
67106c3fb27SDimitry Andric // |SubSectionType|SubSectionSize|Contents...|
67206c3fb27SDimitry Andric uint32_t SubType, SubSectionSize;
67306c3fb27SDimitry Andric if (Error E = consume(Data, SubType))
67406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
67506c3fb27SDimitry Andric if (Error E = consume(Data, SubSectionSize))
67606c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
67706c3fb27SDimitry Andric
67806c3fb27SDimitry Andric // Process the subsection as normal even if the ignore bit is set.
67906c3fb27SDimitry Andric SubType &= ~SubsectionIgnoreFlag;
68006c3fb27SDimitry Andric
68106c3fb27SDimitry Andric // Get the contents of the subsection.
68206c3fb27SDimitry Andric if (SubSectionSize > Data.size())
68306c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
68406c3fb27SDimitry Andric StringRef Contents = Data.substr(0, SubSectionSize);
68506c3fb27SDimitry Andric
68606c3fb27SDimitry Andric // Add SubSectionSize to the current offset and align that offset
68706c3fb27SDimitry Andric // to find the next subsection.
68806c3fb27SDimitry Andric size_t SectionOffset = Data.data() - SectionContents.data();
68906c3fb27SDimitry Andric size_t NextOffset = SectionOffset + SubSectionSize;
69006c3fb27SDimitry Andric NextOffset = alignTo(NextOffset, 4);
69106c3fb27SDimitry Andric if (NextOffset > SectionContents.size())
69206c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
69306c3fb27SDimitry Andric Data = SectionContents.drop_front(NextOffset);
69406c3fb27SDimitry Andric
69506c3fb27SDimitry Andric switch (DebugSubsectionKind(SubType)) {
69606c3fb27SDimitry Andric case DebugSubsectionKind::Symbols:
69706c3fb27SDimitry Andric if (Error Err =
69806c3fb27SDimitry Andric traverseSymbolsSubsection(Contents, Section, SectionContents))
69906c3fb27SDimitry Andric return Err;
70006c3fb27SDimitry Andric break;
70106c3fb27SDimitry Andric
70206c3fb27SDimitry Andric case DebugSubsectionKind::InlineeLines:
70306c3fb27SDimitry Andric if (Error Err = traverseInlineeLines(Contents))
70406c3fb27SDimitry Andric return Err;
70506c3fb27SDimitry Andric break;
70606c3fb27SDimitry Andric
70706c3fb27SDimitry Andric case DebugSubsectionKind::Lines:
70806c3fb27SDimitry Andric // Holds a PC to file:line table. Some data to parse this subsection
70906c3fb27SDimitry Andric // is stored in the other subsections, so just check sanity and store
71006c3fb27SDimitry Andric // the pointers for deferred processing.
71106c3fb27SDimitry Andric
71206c3fb27SDimitry Andric // Collect function and ranges only if we need to print logical lines.
71306c3fb27SDimitry Andric if (options().getGeneralCollectRanges()) {
71406c3fb27SDimitry Andric
71506c3fb27SDimitry Andric if (SubSectionSize < 12) {
71606c3fb27SDimitry Andric // There should be at least three words to store two function
71706c3fb27SDimitry Andric // relocations and size of the code.
71806c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
71906c3fb27SDimitry Andric }
72006c3fb27SDimitry Andric
72106c3fb27SDimitry Andric StringRef SymbolName;
72206c3fb27SDimitry Andric if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
72306c3fb27SDimitry Andric SectionOffset, SymbolName))
72406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(Err)),
72506c3fb27SDimitry Andric getFileName());
72606c3fb27SDimitry Andric
72706c3fb27SDimitry Andric LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
72806c3fb27SDimitry Andric if (FunctionLineTables.count(SymbolName) != 0) {
72906c3fb27SDimitry Andric // Saw debug info for this function already?
73006c3fb27SDimitry Andric return createStringError(object_error::parse_failed, getFileName());
73106c3fb27SDimitry Andric }
73206c3fb27SDimitry Andric
73306c3fb27SDimitry Andric FunctionLineTables[SymbolName] = Contents;
73406c3fb27SDimitry Andric SymbolNames.push_back(SymbolName);
73506c3fb27SDimitry Andric }
73606c3fb27SDimitry Andric break;
73706c3fb27SDimitry Andric
73806c3fb27SDimitry Andric // Do nothing for unrecognized subsections.
73906c3fb27SDimitry Andric default:
74006c3fb27SDimitry Andric break;
74106c3fb27SDimitry Andric }
74206c3fb27SDimitry Andric W.flush();
74306c3fb27SDimitry Andric }
74406c3fb27SDimitry Andric
74506c3fb27SDimitry Andric // Traverse the line tables now that we've read all the subsections and
74606c3fb27SDimitry Andric // know all the required information.
74706c3fb27SDimitry Andric for (StringRef SymbolName : SymbolNames) {
74806c3fb27SDimitry Andric LLVM_DEBUG({
74906c3fb27SDimitry Andric ListScope S(W, "FunctionLineTable");
75006c3fb27SDimitry Andric W.printString("Symbol Name", SymbolName);
75106c3fb27SDimitry Andric });
75206c3fb27SDimitry Andric
7535f757f3fSDimitry Andric BinaryStreamReader Reader(FunctionLineTables[SymbolName],
7545f757f3fSDimitry Andric llvm::endianness::little);
75506c3fb27SDimitry Andric
75606c3fb27SDimitry Andric DebugLinesSubsectionRef Lines;
75706c3fb27SDimitry Andric if (Error E = Lines.initialize(Reader))
75806c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(E)), getFileName());
75906c3fb27SDimitry Andric
76006c3fb27SDimitry Andric // Find the associated symbol table information.
76106c3fb27SDimitry Andric LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName);
76206c3fb27SDimitry Andric LVScope *Function = SymbolTableEntry.Scope;
76306c3fb27SDimitry Andric if (!Function)
76406c3fb27SDimitry Andric continue;
76506c3fb27SDimitry Andric
76606c3fb27SDimitry Andric LVAddress Addendum = SymbolTableEntry.Address;
76706c3fb27SDimitry Andric LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;
76806c3fb27SDimitry Andric
76906c3fb27SDimitry Andric // The given scope represents the function that contains the line numbers.
77006c3fb27SDimitry Andric // Collect all generated debug lines associated with the function.
77106c3fb27SDimitry Andric CULines.clear();
77206c3fb27SDimitry Andric
77306c3fb27SDimitry Andric // For the given scope, collect all scopes ranges.
77406c3fb27SDimitry Andric LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
77506c3fb27SDimitry Andric ScopesWithRanges->clear();
77606c3fb27SDimitry Andric Function->getRanges(*ScopesWithRanges);
77706c3fb27SDimitry Andric ScopesWithRanges->sort();
77806c3fb27SDimitry Andric
77906c3fb27SDimitry Andric uint16_t Segment = Lines.header()->RelocSegment;
78006c3fb27SDimitry Andric uint32_t Begin = Lines.header()->RelocOffset;
78106c3fb27SDimitry Andric uint32_t Size = Lines.header()->CodeSize;
78206c3fb27SDimitry Andric for (const LineColumnEntry &Block : Lines)
78306c3fb27SDimitry Andric if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,
78406c3fb27SDimitry Andric Size, Block.NameIndex))
78506c3fb27SDimitry Andric return Err;
78606c3fb27SDimitry Andric
78706c3fb27SDimitry Andric // Include lines from any inlined functions within the current function.
78806c3fb27SDimitry Andric includeInlineeLines(SectionIndex, Function);
78906c3fb27SDimitry Andric
79006c3fb27SDimitry Andric if (Error Err = createInstructions(Function, SectionIndex))
79106c3fb27SDimitry Andric return Err;
79206c3fb27SDimitry Andric
79306c3fb27SDimitry Andric processLines(&CULines, SectionIndex, Function);
79406c3fb27SDimitry Andric }
79506c3fb27SDimitry Andric
79606c3fb27SDimitry Andric return Error::success();
79706c3fb27SDimitry Andric }
79806c3fb27SDimitry Andric
sortScopes()79906c3fb27SDimitry Andric void LVCodeViewReader::sortScopes() { Root->sort(); }
80006c3fb27SDimitry Andric
print(raw_ostream & OS) const80106c3fb27SDimitry Andric void LVCodeViewReader::print(raw_ostream &OS) const {
80206c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "CreateReaders\n");
80306c3fb27SDimitry Andric }
80406c3fb27SDimitry Andric
mapRangeAddress(const ObjectFile & Obj,const SectionRef & Section,bool IsComdat)80506c3fb27SDimitry Andric void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
80606c3fb27SDimitry Andric const SectionRef &Section,
80706c3fb27SDimitry Andric bool IsComdat) {
80806c3fb27SDimitry Andric if (!Obj.isCOFF())
80906c3fb27SDimitry Andric return;
81006c3fb27SDimitry Andric
81106c3fb27SDimitry Andric const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj);
81206c3fb27SDimitry Andric
81306c3fb27SDimitry Andric for (const SymbolRef &Sym : Object->symbols()) {
81406c3fb27SDimitry Andric if (!Section.containsSymbol(Sym))
81506c3fb27SDimitry Andric continue;
81606c3fb27SDimitry Andric
81706c3fb27SDimitry Andric COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);
81806c3fb27SDimitry Andric if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)
81906c3fb27SDimitry Andric continue;
82006c3fb27SDimitry Andric
82106c3fb27SDimitry Andric StringRef SymbolName;
82206c3fb27SDimitry Andric Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);
82306c3fb27SDimitry Andric if (!SymNameOrErr) {
82406c3fb27SDimitry Andric W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
82506c3fb27SDimitry Andric << "\n";
82606c3fb27SDimitry Andric consumeError(SymNameOrErr.takeError());
82706c3fb27SDimitry Andric continue;
82806c3fb27SDimitry Andric }
82906c3fb27SDimitry Andric SymbolName = *SymNameOrErr;
83006c3fb27SDimitry Andric
83106c3fb27SDimitry Andric LLVM_DEBUG({
83206c3fb27SDimitry Andric Expected<const coff_section *> SectionOrErr =
83306c3fb27SDimitry Andric Object->getSection(Symbol.getSectionNumber());
83406c3fb27SDimitry Andric if (!SectionOrErr) {
83506c3fb27SDimitry Andric W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
83606c3fb27SDimitry Andric << "\n";
83706c3fb27SDimitry Andric consumeError(SectionOrErr.takeError());
83806c3fb27SDimitry Andric return;
83906c3fb27SDimitry Andric }
84006c3fb27SDimitry Andric W.printNumber("Section #", Symbol.getSectionNumber());
84106c3fb27SDimitry Andric W.printString("Name", SymbolName);
84206c3fb27SDimitry Andric W.printHex("Value", Symbol.getValue());
84306c3fb27SDimitry Andric });
84406c3fb27SDimitry Andric
84506c3fb27SDimitry Andric // Record the symbol name (linkage) and its loading address.
84606c3fb27SDimitry Andric addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(),
84706c3fb27SDimitry Andric IsComdat);
84806c3fb27SDimitry Andric }
84906c3fb27SDimitry Andric }
85006c3fb27SDimitry Andric
createScopes(COFFObjectFile & Obj)85106c3fb27SDimitry Andric Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {
85206c3fb27SDimitry Andric if (Error Err = loadTargetInfo(Obj))
85306c3fb27SDimitry Andric return Err;
85406c3fb27SDimitry Andric
85506c3fb27SDimitry Andric // Initialization required when processing a COFF file:
85606c3fb27SDimitry Andric // Cache the symbols relocations.
85706c3fb27SDimitry Andric // Create a mapping for virtual addresses.
85806c3fb27SDimitry Andric // Get the functions entry points.
85906c3fb27SDimitry Andric cacheRelocations();
86006c3fb27SDimitry Andric mapVirtualAddress(Obj);
86106c3fb27SDimitry Andric
86206c3fb27SDimitry Andric for (const SectionRef &Section : Obj.sections()) {
86306c3fb27SDimitry Andric Expected<StringRef> SectionNameOrErr = Section.getName();
86406c3fb27SDimitry Andric if (!SectionNameOrErr)
86506c3fb27SDimitry Andric return SectionNameOrErr.takeError();
86606c3fb27SDimitry Andric // .debug$T is a standard CodeView type section, while .debug$P is the
86706c3fb27SDimitry Andric // same format but used for MSVC precompiled header object files.
86806c3fb27SDimitry Andric if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
86906c3fb27SDimitry Andric if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))
87006c3fb27SDimitry Andric return Err;
87106c3fb27SDimitry Andric }
87206c3fb27SDimitry Andric
87306c3fb27SDimitry Andric // Process collected namespaces.
87406c3fb27SDimitry Andric LogicalVisitor.processNamespaces();
87506c3fb27SDimitry Andric
87606c3fb27SDimitry Andric for (const SectionRef &Section : Obj.sections()) {
87706c3fb27SDimitry Andric Expected<StringRef> SectionNameOrErr = Section.getName();
87806c3fb27SDimitry Andric if (!SectionNameOrErr)
87906c3fb27SDimitry Andric return SectionNameOrErr.takeError();
88006c3fb27SDimitry Andric if (*SectionNameOrErr == ".debug$S")
88106c3fb27SDimitry Andric if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
88206c3fb27SDimitry Andric return Err;
88306c3fb27SDimitry Andric }
88406c3fb27SDimitry Andric
88506c3fb27SDimitry Andric // Check if we have to close the Compile Unit scope.
88606c3fb27SDimitry Andric LogicalVisitor.closeScope();
88706c3fb27SDimitry Andric
88806c3fb27SDimitry Andric // Traverse the strings recorded and transform them into filenames.
88906c3fb27SDimitry Andric LogicalVisitor.processFiles();
89006c3fb27SDimitry Andric
89106c3fb27SDimitry Andric // Process collected element lines.
89206c3fb27SDimitry Andric LogicalVisitor.processLines();
89306c3fb27SDimitry Andric
89406c3fb27SDimitry Andric // Translate composite names into a single component.
89506c3fb27SDimitry Andric Root->transformScopedName();
89606c3fb27SDimitry Andric return Error::success();
89706c3fb27SDimitry Andric }
89806c3fb27SDimitry Andric
createScopes(PDBFile & Pdb)89906c3fb27SDimitry Andric Error LVCodeViewReader::createScopes(PDBFile &Pdb) {
90006c3fb27SDimitry Andric if (Error Err = loadTargetInfo(Pdb))
90106c3fb27SDimitry Andric return Err;
90206c3fb27SDimitry Andric
90306c3fb27SDimitry Andric if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())
90406c3fb27SDimitry Andric return Error::success();
90506c3fb27SDimitry Andric
90606c3fb27SDimitry Andric // Open the executable associated with the PDB file and get the section
90706c3fb27SDimitry Andric // addresses used to calculate linear addresses for CodeView Symbols.
90806c3fb27SDimitry Andric if (!ExePath.empty()) {
90906c3fb27SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
91006c3fb27SDimitry Andric MemoryBuffer::getFileOrSTDIN(ExePath);
91106c3fb27SDimitry Andric if (BuffOrErr.getError()) {
91206c3fb27SDimitry Andric return createStringError(errc::bad_file_descriptor,
91306c3fb27SDimitry Andric "File '%s' does not exist.", ExePath.c_str());
91406c3fb27SDimitry Andric }
91506c3fb27SDimitry Andric BinaryBuffer = std::move(BuffOrErr.get());
91606c3fb27SDimitry Andric
91706c3fb27SDimitry Andric // Check if the buffer corresponds to a PECOFF executable.
91806c3fb27SDimitry Andric assert(identify_magic(BinaryBuffer->getBuffer()) ==
91906c3fb27SDimitry Andric file_magic::pecoff_executable &&
92006c3fb27SDimitry Andric "Invalid PECOFF executable file.");
92106c3fb27SDimitry Andric
92206c3fb27SDimitry Andric Expected<std::unique_ptr<Binary>> BinOrErr =
92306c3fb27SDimitry Andric createBinary(BinaryBuffer->getMemBufferRef());
92406c3fb27SDimitry Andric if (errorToErrorCode(BinOrErr.takeError())) {
92506c3fb27SDimitry Andric return createStringError(errc::not_supported,
92606c3fb27SDimitry Andric "Binary object format in '%s' is not supported.",
92706c3fb27SDimitry Andric ExePath.c_str());
92806c3fb27SDimitry Andric }
92906c3fb27SDimitry Andric BinaryExecutable = std::move(*BinOrErr);
93006c3fb27SDimitry Andric if (COFFObjectFile *COFFObject =
93106c3fb27SDimitry Andric dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
93206c3fb27SDimitry Andric mapVirtualAddress(*COFFObject);
93306c3fb27SDimitry Andric }
93406c3fb27SDimitry Andric
93506c3fb27SDimitry Andric // In order to generate a full logical view, we have to traverse both
93606c3fb27SDimitry Andric // streams TPI and IPI if they are present. The following table gives
93706c3fb27SDimitry Andric // the stream where a specified type is located. If the IPI stream is
93806c3fb27SDimitry Andric // not present, all the types are located in the TPI stream.
93906c3fb27SDimitry Andric //
94006c3fb27SDimitry Andric // TPI Stream:
94106c3fb27SDimitry Andric // LF_POINTER LF_MODIFIER LF_PROCEDURE LF_MFUNCTION
94206c3fb27SDimitry Andric // LF_LABEL LF_ARGLIST LF_FIELDLIST LF_ARRAY
94306c3fb27SDimitry Andric // LF_CLASS LF_STRUCTURE LF_INTERFACE LF_UNION
94406c3fb27SDimitry Andric // LF_ENUM LF_TYPESERVER2 LF_VFTABLE LF_VTSHAPE
94506c3fb27SDimitry Andric // LF_BITFIELD LF_METHODLIST LF_PRECOMP LF_ENDPRECOMP
94606c3fb27SDimitry Andric //
94706c3fb27SDimitry Andric // IPI stream:
94806c3fb27SDimitry Andric // LF_FUNC_ID LF_MFUNC_ID LF_BUILDINFO
94906c3fb27SDimitry Andric // LF_SUBSTR_LIST LF_STRING_ID LF_UDT_SRC_LINE
95006c3fb27SDimitry Andric // LF_UDT_MOD_SRC_LINE
95106c3fb27SDimitry Andric
95206c3fb27SDimitry Andric LazyRandomTypeCollection &Types = types();
95306c3fb27SDimitry Andric LazyRandomTypeCollection &Ids = ids();
95406c3fb27SDimitry Andric if (Error Err = traverseTypes(Pdb, Types, Ids))
95506c3fb27SDimitry Andric return Err;
95606c3fb27SDimitry Andric
95706c3fb27SDimitry Andric // Process collected namespaces.
95806c3fb27SDimitry Andric LogicalVisitor.processNamespaces();
95906c3fb27SDimitry Andric
96006c3fb27SDimitry Andric LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });
96106c3fb27SDimitry Andric
96206c3fb27SDimitry Andric auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
96306c3fb27SDimitry Andric DebugInlineeLinesSubsectionRef &Lines) -> Error {
96406c3fb27SDimitry Andric return collectInlineeInfo(Lines, &SG);
96506c3fb27SDimitry Andric };
96606c3fb27SDimitry Andric
96706c3fb27SDimitry Andric FilterOptions Filters = {};
96806c3fb27SDimitry Andric LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);
96906c3fb27SDimitry Andric const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);
97006c3fb27SDimitry Andric if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
97106c3fb27SDimitry Andric Input, HeaderScope, VisitInlineeLines))
97206c3fb27SDimitry Andric return Err;
97306c3fb27SDimitry Andric
97406c3fb27SDimitry Andric // Traverse global symbols.
97506c3fb27SDimitry Andric LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
97606c3fb27SDimitry Andric if (Pdb.hasPDBGlobalsStream()) {
97706c3fb27SDimitry Andric Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
97806c3fb27SDimitry Andric if (!GlobalsOrErr)
97906c3fb27SDimitry Andric return GlobalsOrErr.takeError();
98006c3fb27SDimitry Andric GlobalsStream &Globals = *GlobalsOrErr;
98106c3fb27SDimitry Andric const GSIHashTable &Table = Globals.getGlobalsTable();
98206c3fb27SDimitry Andric Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
98306c3fb27SDimitry Andric if (ExpectedSyms) {
98406c3fb27SDimitry Andric
98506c3fb27SDimitry Andric SymbolVisitorCallbackPipeline Pipeline;
98606c3fb27SDimitry Andric SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
98706c3fb27SDimitry Andric LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
98806c3fb27SDimitry Andric LogicalVisitor.getShared());
98906c3fb27SDimitry Andric
99006c3fb27SDimitry Andric // As the global symbols do not have an associated Compile Unit, create
99106c3fb27SDimitry Andric // one, as the container for all global symbols.
99206c3fb27SDimitry Andric RecordPrefix Prefix(SymbolKind::S_COMPILE3);
99306c3fb27SDimitry Andric CVSymbol Symbol(&Prefix, sizeof(Prefix));
99406c3fb27SDimitry Andric uint32_t Offset = 0;
99506c3fb27SDimitry Andric if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))
99606c3fb27SDimitry Andric consumeError(std::move(Err));
99706c3fb27SDimitry Andric else {
99806c3fb27SDimitry Andric // The CodeView compile unit containing the global symbols does not
99906c3fb27SDimitry Andric // have a name; generate one using its parent name (object filename)
100006c3fb27SDimitry Andric // follow by the '_global' string.
100106c3fb27SDimitry Andric std::string Name(CompileUnit->getParentScope()->getName());
100206c3fb27SDimitry Andric CompileUnit->setName(Name.append("_global"));
100306c3fb27SDimitry Andric
100406c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Deserializer);
100506c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Traverser);
100606c3fb27SDimitry Andric CVSymbolVisitor Visitor(Pipeline);
100706c3fb27SDimitry Andric
100806c3fb27SDimitry Andric BinaryStreamRef SymStream =
100906c3fb27SDimitry Andric ExpectedSyms->getSymbolArray().getUnderlyingStream();
101006c3fb27SDimitry Andric for (uint32_t PubSymOff : Table) {
101106c3fb27SDimitry Andric Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
101206c3fb27SDimitry Andric if (Sym) {
101306c3fb27SDimitry Andric if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
101406c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(Err)),
101506c3fb27SDimitry Andric getFileName());
101606c3fb27SDimitry Andric } else {
101706c3fb27SDimitry Andric consumeError(Sym.takeError());
101806c3fb27SDimitry Andric }
101906c3fb27SDimitry Andric }
102006c3fb27SDimitry Andric }
102106c3fb27SDimitry Andric
102206c3fb27SDimitry Andric LogicalVisitor.closeScope();
102306c3fb27SDimitry Andric } else {
102406c3fb27SDimitry Andric consumeError(ExpectedSyms.takeError());
102506c3fb27SDimitry Andric }
102606c3fb27SDimitry Andric }
102706c3fb27SDimitry Andric
102806c3fb27SDimitry Andric // Traverse symbols (DBI).
102906c3fb27SDimitry Andric LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });
103006c3fb27SDimitry Andric
103106c3fb27SDimitry Andric auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
103206c3fb27SDimitry Andric Expected<ModuleDebugStreamRef> ExpectedModS =
103306c3fb27SDimitry Andric getModuleDebugStream(Pdb, Modi);
103406c3fb27SDimitry Andric if (ExpectedModS) {
103506c3fb27SDimitry Andric ModuleDebugStreamRef &ModS = *ExpectedModS;
103606c3fb27SDimitry Andric
103706c3fb27SDimitry Andric LLVM_DEBUG({
103806c3fb27SDimitry Andric W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
103906c3fb27SDimitry Andric });
104006c3fb27SDimitry Andric
104106c3fb27SDimitry Andric SymbolVisitorCallbackPipeline Pipeline;
104206c3fb27SDimitry Andric SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
104306c3fb27SDimitry Andric LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
104406c3fb27SDimitry Andric LogicalVisitor.getShared());
104506c3fb27SDimitry Andric
104606c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Deserializer);
104706c3fb27SDimitry Andric Pipeline.addCallbackToPipeline(Traverser);
104806c3fb27SDimitry Andric CVSymbolVisitor Visitor(Pipeline);
104906c3fb27SDimitry Andric BinarySubstreamRef SS = ModS.getSymbolsSubstream();
105006c3fb27SDimitry Andric if (Error Err =
105106c3fb27SDimitry Andric Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))
105206c3fb27SDimitry Andric return createStringError(errorToErrorCode(std::move(Err)),
105306c3fb27SDimitry Andric getFileName());
105406c3fb27SDimitry Andric } else {
105506c3fb27SDimitry Andric // If the module stream does not exist, it is not an error condition.
105606c3fb27SDimitry Andric consumeError(ExpectedModS.takeError());
105706c3fb27SDimitry Andric }
105806c3fb27SDimitry Andric
105906c3fb27SDimitry Andric return Error::success();
106006c3fb27SDimitry Andric };
106106c3fb27SDimitry Andric
106206c3fb27SDimitry Andric if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup))
106306c3fb27SDimitry Andric return Err;
106406c3fb27SDimitry Andric
106506c3fb27SDimitry Andric // At this stage, the logical view contains all scopes, symbols and types.
106606c3fb27SDimitry Andric // For PDBs we can use the module id, to access its specific compile unit.
106706c3fb27SDimitry Andric // The line record addresses has been already resolved, so we can apply the
106806c3fb27SDimitry Andric // flow as when processing DWARF.
106906c3fb27SDimitry Andric
107006c3fb27SDimitry Andric LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });
107106c3fb27SDimitry Andric
107206c3fb27SDimitry Andric // Record all line records for a Compile Unit.
107306c3fb27SDimitry Andric CULines.clear();
107406c3fb27SDimitry Andric
107506c3fb27SDimitry Andric auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
107606c3fb27SDimitry Andric DebugLinesSubsectionRef &Lines) -> Error {
107706c3fb27SDimitry Andric if (!options().getPrintLines())
107806c3fb27SDimitry Andric return Error::success();
107906c3fb27SDimitry Andric
108006c3fb27SDimitry Andric uint16_t Segment = Lines.header()->RelocSegment;
108106c3fb27SDimitry Andric uint32_t Begin = Lines.header()->RelocOffset;
108206c3fb27SDimitry Andric uint32_t Size = Lines.header()->CodeSize;
108306c3fb27SDimitry Andric
108406c3fb27SDimitry Andric LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });
108506c3fb27SDimitry Andric
108606c3fb27SDimitry Andric // We have line information for a new module; finish processing the
108706c3fb27SDimitry Andric // collected information for the current module. Once it is done, start
108806c3fb27SDimitry Andric // recording the line information for the new module.
108906c3fb27SDimitry Andric if (CurrentModule != Modi) {
109006c3fb27SDimitry Andric if (Error Err = processModule())
109106c3fb27SDimitry Andric return Err;
109206c3fb27SDimitry Andric CULines.clear();
109306c3fb27SDimitry Andric CurrentModule = Modi;
109406c3fb27SDimitry Andric }
109506c3fb27SDimitry Andric
109606c3fb27SDimitry Andric for (const LineColumnEntry &Block : Lines)
109706c3fb27SDimitry Andric if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment,
109806c3fb27SDimitry Andric Begin, Size, Block.NameIndex, &SG))
109906c3fb27SDimitry Andric return Err;
110006c3fb27SDimitry Andric
110106c3fb27SDimitry Andric return Error::success();
110206c3fb27SDimitry Andric };
110306c3fb27SDimitry Andric
110406c3fb27SDimitry Andric if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
110506c3fb27SDimitry Andric Input, HeaderScope, VisitDebugLines))
110606c3fb27SDimitry Andric return Err;
110706c3fb27SDimitry Andric
110806c3fb27SDimitry Andric // Check if we have to close the Compile Unit scope.
110906c3fb27SDimitry Andric LogicalVisitor.closeScope();
111006c3fb27SDimitry Andric
111106c3fb27SDimitry Andric // Process collected element lines.
111206c3fb27SDimitry Andric LogicalVisitor.processLines();
111306c3fb27SDimitry Andric
111406c3fb27SDimitry Andric // Translate composite names into a single component.
111506c3fb27SDimitry Andric Root->transformScopedName();
111606c3fb27SDimitry Andric return Error::success();
111706c3fb27SDimitry Andric }
111806c3fb27SDimitry Andric
processModule()111906c3fb27SDimitry Andric Error LVCodeViewReader::processModule() {
112006c3fb27SDimitry Andric if (LVScope *Scope = getScopeForModule(CurrentModule)) {
112106c3fb27SDimitry Andric CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);
112206c3fb27SDimitry Andric
112306c3fb27SDimitry Andric LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });
112406c3fb27SDimitry Andric
112506c3fb27SDimitry Andric // For the given compile unit, collect all scopes ranges.
112606c3fb27SDimitry Andric // For a complete ranges and lines mapping, the logical view support
112706c3fb27SDimitry Andric // needs for the compile unit to have a low and high pc values. We
112806c3fb27SDimitry Andric // can traverse the 'Modules' section and get the information for the
112906c3fb27SDimitry Andric // specific module. Another option, is from all the ranges collected
113006c3fb27SDimitry Andric // to take the first and last values.
113106c3fb27SDimitry Andric LVSectionIndex SectionIndex = DotTextSectionIndex;
113206c3fb27SDimitry Andric LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
113306c3fb27SDimitry Andric ScopesWithRanges->clear();
113406c3fb27SDimitry Andric CompileUnit->getRanges(*ScopesWithRanges);
113506c3fb27SDimitry Andric if (!ScopesWithRanges->empty())
113606c3fb27SDimitry Andric CompileUnit->addObject(ScopesWithRanges->getLower(),
113706c3fb27SDimitry Andric ScopesWithRanges->getUpper());
113806c3fb27SDimitry Andric ScopesWithRanges->sort();
113906c3fb27SDimitry Andric
114006c3fb27SDimitry Andric if (Error Err = createInstructions())
114106c3fb27SDimitry Andric return Err;
114206c3fb27SDimitry Andric
114306c3fb27SDimitry Andric // Include lines from any inlined functions within the current function.
114406c3fb27SDimitry Andric includeInlineeLines(SectionIndex, Scope);
114506c3fb27SDimitry Andric
114606c3fb27SDimitry Andric processLines(&CULines, SectionIndex, nullptr);
114706c3fb27SDimitry Andric }
114806c3fb27SDimitry Andric
114906c3fb27SDimitry Andric return Error::success();
115006c3fb27SDimitry Andric }
115106c3fb27SDimitry Andric
115206c3fb27SDimitry Andric // In order to create the scopes, the CodeView Reader will:
115306c3fb27SDimitry Andric // = Traverse the TPI/IPI stream (Type visitor):
115406c3fb27SDimitry Andric // Collect forward references, scoped names, type indexes that will represent
115506c3fb27SDimitry Andric // a logical element, strings, line records, linkage names.
115606c3fb27SDimitry Andric // = Traverse the symbols section (Symbol visitor):
115706c3fb27SDimitry Andric // Create the scopes tree and creates the required logical elements, by
115806c3fb27SDimitry Andric // using the collected indexes from the type visitor.
createScopes()115906c3fb27SDimitry Andric Error LVCodeViewReader::createScopes() {
116006c3fb27SDimitry Andric LLVM_DEBUG({
116106c3fb27SDimitry Andric W.startLine() << "\n";
116206c3fb27SDimitry Andric W.printString("File", getFileName().str());
116306c3fb27SDimitry Andric W.printString("Exe", ExePath);
116406c3fb27SDimitry Andric W.printString("Format", FileFormatName);
116506c3fb27SDimitry Andric });
116606c3fb27SDimitry Andric
116706c3fb27SDimitry Andric if (Error Err = LVReader::createScopes())
116806c3fb27SDimitry Andric return Err;
116906c3fb27SDimitry Andric
117006c3fb27SDimitry Andric LogicalVisitor.setRoot(Root);
117106c3fb27SDimitry Andric
117206c3fb27SDimitry Andric if (isObj()) {
117306c3fb27SDimitry Andric if (Error Err = createScopes(getObj()))
117406c3fb27SDimitry Andric return Err;
117506c3fb27SDimitry Andric } else {
117606c3fb27SDimitry Andric if (Error Err = createScopes(getPdb()))
117706c3fb27SDimitry Andric return Err;
117806c3fb27SDimitry Andric }
117906c3fb27SDimitry Andric
118006c3fb27SDimitry Andric return Error::success();
118106c3fb27SDimitry Andric }
118206c3fb27SDimitry Andric
loadTargetInfo(const ObjectFile & Obj)118306c3fb27SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
118406c3fb27SDimitry Andric // Detect the architecture from the object file. We usually don't need OS
118506c3fb27SDimitry Andric // info to lookup a target and create register info.
118606c3fb27SDimitry Andric Triple TT;
118706c3fb27SDimitry Andric TT.setArch(Triple::ArchType(Obj.getArch()));
118806c3fb27SDimitry Andric TT.setVendor(Triple::UnknownVendor);
118906c3fb27SDimitry Andric TT.setOS(Triple::UnknownOS);
119006c3fb27SDimitry Andric
119106c3fb27SDimitry Andric // Features to be passed to target/subtarget
119206c3fb27SDimitry Andric Expected<SubtargetFeatures> Features = Obj.getFeatures();
119306c3fb27SDimitry Andric SubtargetFeatures FeaturesValue;
119406c3fb27SDimitry Andric if (!Features) {
119506c3fb27SDimitry Andric consumeError(Features.takeError());
119606c3fb27SDimitry Andric FeaturesValue = SubtargetFeatures();
119706c3fb27SDimitry Andric }
119806c3fb27SDimitry Andric FeaturesValue = *Features;
119906c3fb27SDimitry Andric return loadGenericTargetInfo(TT.str(), FeaturesValue.getString());
120006c3fb27SDimitry Andric }
120106c3fb27SDimitry Andric
loadTargetInfo(const PDBFile & Pdb)120206c3fb27SDimitry Andric Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
120306c3fb27SDimitry Andric Triple TT;
120406c3fb27SDimitry Andric TT.setArch(Triple::ArchType::x86_64);
120506c3fb27SDimitry Andric TT.setVendor(Triple::UnknownVendor);
120606c3fb27SDimitry Andric TT.setOS(Triple::Win32);
120706c3fb27SDimitry Andric
120806c3fb27SDimitry Andric StringRef TheFeature = "";
120906c3fb27SDimitry Andric
121006c3fb27SDimitry Andric return loadGenericTargetInfo(TT.str(), TheFeature);
121106c3fb27SDimitry Andric }
121206c3fb27SDimitry Andric
getRegisterName(LVSmall Opcode,ArrayRef<uint64_t> Operands)121306c3fb27SDimitry Andric std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,
121406c3fb27SDimitry Andric ArrayRef<uint64_t> Operands) {
121506c3fb27SDimitry Andric // Get Compilation Unit CPU Type.
121606c3fb27SDimitry Andric CPUType CPU = getCompileUnitCPUType();
121706c3fb27SDimitry Andric // For CodeView the register always is in Operands[0];
121806c3fb27SDimitry Andric RegisterId Register = (RegisterId(Operands[0]));
121906c3fb27SDimitry Andric return formatRegisterId(Register, CPU);
122006c3fb27SDimitry Andric }
1221