//===-- LVCodeViewReader.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This implements the LVCodeViewReader class.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/LogicalView/Readers/LVCodeViewReader.h"
#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/WithColor.h"

using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::logicalview;
using namespace llvm::msf;
using namespace llvm::object;
using namespace llvm::pdb;

#define DEBUG_TYPE "CodeViewReader"

StringRef LVCodeViewReader::getSymbolKindName(SymbolKind Kind) {
  switch (Kind) {
#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
  case EnumName:                                                               \
    return #EnumName;
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
  default:
    return "UnknownSym";
  }
  llvm_unreachable("Unknown SymbolKind::Kind");
}

std::string LVCodeViewReader::formatRegisterId(RegisterId Register,
                                               CPUType CPU) {
#define RETURN_CASE(Enum, X, Ret)                                              \
  case Enum::X:                                                                \
    return Ret;

  if (CPU == CPUType::ARMNT) {
    switch (Register) {
#define CV_REGISTERS_ARM
#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
#undef CV_REGISTER
#undef CV_REGISTERS_ARM

    default:
      break;
    }
  } else if (CPU == CPUType::ARM64) {
    switch (Register) {
#define CV_REGISTERS_ARM64
#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
#undef CV_REGISTER
#undef CV_REGISTERS_ARM64

    default:
      break;
    }
  } else {
    switch (Register) {
#define CV_REGISTERS_X86
#define CV_REGISTER(name, val) RETURN_CASE(RegisterId, name, #name)
#include "llvm/DebugInfo/CodeView/CodeViewRegisters.def"
#undef CV_REGISTER
#undef CV_REGISTERS_X86

    default:
      break;
    }
  }
  return "formatUnknownEnum(Id)";
}

void LVCodeViewReader::printRelocatedField(StringRef Label,
                                           const coff_section *CoffSection,
                                           uint32_t RelocOffset,
                                           uint32_t Offset,
                                           StringRef *RelocSym) {
  StringRef SymStorage;
  StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
  if (!resolveSymbolName(CoffSection, RelocOffset, Symbol))
    W.printSymbolOffset(Label, Symbol, Offset);
  else
    W.printHex(Label, RelocOffset);
}

void LVCodeViewReader::getLinkageName(const coff_section *CoffSection,
                                      uint32_t RelocOffset, uint32_t Offset,
                                      StringRef *RelocSym) {
  StringRef SymStorage;
  StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
  if (resolveSymbolName(CoffSection, RelocOffset, Symbol))
    Symbol = "";
}

Expected<StringRef>
LVCodeViewReader::getFileNameForFileOffset(uint32_t FileOffset,
                                           const SymbolGroup *SG) {
  if (SG) {
    Expected<StringRef> Filename = SG->getNameFromChecksums(FileOffset);
    if (!Filename) {
      consumeError(Filename.takeError());
      return StringRef("");
    }
    return *Filename;
  }

  // The file checksum subsection should precede all references to it.
  if (!CVFileChecksumTable.valid() || !CVStringTable.valid())
    return createStringError(object_error::parse_failed, getFileName());

  VarStreamArray<FileChecksumEntry>::Iterator Iter =
      CVFileChecksumTable.getArray().at(FileOffset);

  // Check if the file checksum table offset is valid.
  if (Iter == CVFileChecksumTable.end())
    return createStringError(object_error::parse_failed, getFileName());

  Expected<StringRef> NameOrErr = CVStringTable.getString(Iter->FileNameOffset);
  if (!NameOrErr)
    return createStringError(object_error::parse_failed, getFileName());
  return *NameOrErr;
}

Error LVCodeViewReader::printFileNameForOffset(StringRef Label,
                                               uint32_t FileOffset,
                                               const SymbolGroup *SG) {
  Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
  if (!NameOrErr)
    return NameOrErr.takeError();
  W.printHex(Label, *NameOrErr, FileOffset);
  return Error::success();
}

void LVCodeViewReader::cacheRelocations() {
  for (const SectionRef &Section : getObj().sections()) {
    const coff_section *CoffSection = getObj().getCOFFSection(Section);

    for (const RelocationRef &Relocacion : Section.relocations())
      RelocMap[CoffSection].push_back(Relocacion);

    // Sort relocations by address.
    llvm::sort(RelocMap[CoffSection], [](RelocationRef L, RelocationRef R) {
      return L.getOffset() < R.getOffset();
    });
  }
}

// Given a section and an offset into this section the function returns the
// symbol used for the relocation at the offset.
Error LVCodeViewReader::resolveSymbol(const coff_section *CoffSection,
                                      uint64_t Offset, SymbolRef &Sym) {
  const auto &Relocations = RelocMap[CoffSection];
  basic_symbol_iterator SymI = getObj().symbol_end();
  for (const RelocationRef &Relocation : Relocations) {
    uint64_t RelocationOffset = Relocation.getOffset();

    if (RelocationOffset == Offset) {
      SymI = Relocation.getSymbol();
      break;
    }
  }
  if (SymI == getObj().symbol_end())
    return make_error<StringError>("Unknown Symbol", inconvertibleErrorCode());
  Sym = *SymI;
  return ErrorSuccess();
}

// Given a section and an offset into this section the function returns the
// name of the symbol used for the relocation at the offset.
Error LVCodeViewReader::resolveSymbolName(const coff_section *CoffSection,
                                          uint64_t Offset, StringRef &Name) {
  SymbolRef Symbol;
  if (Error E = resolveSymbol(CoffSection, Offset, Symbol))
    return E;
  Expected<StringRef> NameOrErr = Symbol.getName();
  if (!NameOrErr)
    return NameOrErr.takeError();
  Name = *NameOrErr;
  return ErrorSuccess();
}

// CodeView and DWARF can have references to compiler generated elements,
// used for initialization. The MSVC includes in the PDBs, internal compile
// units, associated with the MS runtime support. We mark them as 'system'
// and they are printed only if the command line option 'internal=system'.
bool LVCodeViewReader::isSystemEntry(LVElement *Element, StringRef Name) const {
  Name = Name.empty() ? Element->getName() : Name;
  auto Find = [=](const char *String) -> bool { return Name.contains(String); };
  auto Starts = [=](const char *Pattern) -> bool {
    return Name.starts_with(Pattern);
  };
  auto CheckExclude = [&]() -> bool {
    if (Starts("__") || Starts("_PMD") || Starts("_PMFN"))
      return true;
    if (Find("_s__"))
      return true;
    if (Find("_CatchableType") || Find("_TypeDescriptor"))
      return true;
    if (Find("Intermediate\\vctools"))
      return true;
    if (Find("$initializer$") || Find("dynamic initializer"))
      return true;
    if (Find("`vftable'") || Find("_GLOBAL__sub"))
      return true;
    return false;
  };
  bool Excluded = CheckExclude();
  if (Excluded)
    Element->setIsSystem();

  return Excluded;
}

Error LVCodeViewReader::collectInlineeInfo(
    DebugInlineeLinesSubsectionRef &Lines, const llvm::pdb::SymbolGroup *SG) {
  for (const InlineeSourceLine &Line : Lines) {
    TypeIndex TIInlinee = Line.Header->Inlinee;
    uint32_t LineNumber = Line.Header->SourceLineNum;
    uint32_t FileOffset = Line.Header->FileID;
    LLVM_DEBUG({
      DictScope S(W, "InlineeSourceLine");
      LogicalVisitor.printTypeIndex("Inlinee", TIInlinee, StreamTPI);
      if (Error Err = printFileNameForOffset("FileID", FileOffset, SG))
        return Err;
      W.printNumber("SourceLineNum", LineNumber);

      if (Lines.hasExtraFiles()) {
        W.printNumber("ExtraFileCount", Line.ExtraFiles.size());
        ListScope ExtraFiles(W, "ExtraFiles");
        for (const ulittle32_t &FID : Line.ExtraFiles)
          if (Error Err = printFileNameForOffset("FileID", FID, SG))
            return Err;
      }
    });
    Expected<StringRef> NameOrErr = getFileNameForFileOffset(FileOffset, SG);
    if (!NameOrErr)
      return NameOrErr.takeError();
    LogicalVisitor.addInlineeInfo(TIInlinee, LineNumber, *NameOrErr);
  }

  return Error::success();
}

Error LVCodeViewReader::traverseInlineeLines(StringRef Subsection) {
  BinaryStreamReader SR(Subsection, llvm::endianness::little);
  DebugInlineeLinesSubsectionRef Lines;
  if (Error E = Lines.initialize(SR))
    return createStringError(errorToErrorCode(std::move(E)), getFileName());

  return collectInlineeInfo(Lines);
}

Error LVCodeViewReader::createLines(
    const FixedStreamArray<LineNumberEntry> &LineNumbers, LVAddress Addendum,
    uint32_t Segment, uint32_t Begin, uint32_t Size, uint32_t NameIndex,
    const SymbolGroup *SG) {
  LLVM_DEBUG({
    uint32_t End = Begin + Size;
    W.getOStream() << formatv("{0:x-4}:{1:x-8}-{2:x-8}\n", Segment, Begin, End);
  });

  for (const LineNumberEntry &Line : LineNumbers) {
    if (Line.Offset >= Size)
      return createStringError(object_error::parse_failed, getFileName());

    LineInfo LI(Line.Flags);

    LLVM_DEBUG({
      W.getOStream() << formatv(
          "{0} {1:x-8}\n", utostr(LI.getStartLine()),
          fmt_align(Begin + Line.Offset, AlignStyle::Right, 8, '0'));
    });

    // The 'processLines()' function will move each created logical line
    // to its enclosing logical scope, using the debug ranges information
    // and they will be released when its scope parent is deleted.
    LVLineDebug *LineDebug = createLineDebug();
    CULines.push_back(LineDebug);
    LVAddress Address = linearAddress(Segment, Begin + Line.Offset);
    LineDebug->setAddress(Address + Addendum);

    if (LI.isAlwaysStepInto())
      LineDebug->setIsAlwaysStepInto();
    else if (LI.isNeverStepInto())
      LineDebug->setIsNeverStepInto();
    else
      LineDebug->setLineNumber(LI.getStartLine());

    if (LI.isStatement())
      LineDebug->setIsNewStatement();

    Expected<StringRef> NameOrErr = getFileNameForFileOffset(NameIndex, SG);
    if (!NameOrErr)
      return NameOrErr.takeError();
    LineDebug->setFilename(*NameOrErr);
  }

  return Error::success();
}

Error LVCodeViewReader::initializeFileAndStringTables(
    BinaryStreamReader &Reader) {
  while (Reader.bytesRemaining() > 0 &&
         (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {
    // The section consists of a number of subsection in the following format:
    // |SubSectionType|SubSectionSize|Contents...|
    uint32_t SubType, SubSectionSize;

    if (Error E = Reader.readInteger(SubType))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());
    if (Error E = Reader.readInteger(SubSectionSize))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());

    StringRef Contents;
    if (Error E = Reader.readFixedString(Contents, SubSectionSize))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());

    BinaryStreamRef ST(Contents, llvm::endianness::little);
    switch (DebugSubsectionKind(SubType)) {
    case DebugSubsectionKind::FileChecksums:
      if (Error E = CVFileChecksumTable.initialize(ST))
        return createStringError(errorToErrorCode(std::move(E)), getFileName());
      break;
    case DebugSubsectionKind::StringTable:
      if (Error E = CVStringTable.initialize(ST))
        return createStringError(errorToErrorCode(std::move(E)), getFileName());
      break;
    default:
      break;
    }

    uint32_t PaddedSize = alignTo(SubSectionSize, 4);
    if (Error E = Reader.skip(PaddedSize - SubSectionSize))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());
  }

  return Error::success();
}

Error LVCodeViewReader::loadTypeServer(TypeServer2Record &TS) {
  LLVM_DEBUG({
    W.printString("Guid", formatv("{0}", TS.getGuid()).str());
    W.printNumber("Age", TS.getAge());
    W.printString("Name", TS.getName());
  });

  SmallString<128> ServerName(TS.getName());
  BuffOrErr = MemoryBuffer::getFile(ServerName);
  if (BuffOrErr.getError()) {
    // The server name does not exist. Try in the same directory as the
    // input file.
    ServerName = createAlternativePath(ServerName);
    BuffOrErr = MemoryBuffer::getFile(ServerName);
    if (BuffOrErr.getError()) {
      // For the error message, use the original type server name.
      return createStringError(errc::bad_file_descriptor,
                               "File '%s' does not exist.",
                               TS.getName().str().c_str());
    }
  }
  MemBuffer = std::move(BuffOrErr.get());

  // Check if the buffer corresponds to a PDB file.
  assert(identify_magic((*MemBuffer).getBuffer()) == file_magic::pdb &&
         "Invalid PDB file.");

  if (Error Err = loadDataForPDB(PDB_ReaderType::Native, ServerName, Session))
    return createStringError(errorToErrorCode(std::move(Err)), "%s",
                             ServerName.c_str());

  PdbSession.reset(static_cast<NativeSession *>(Session.release()));
  PDBFile &Pdb = PdbSession->getPDBFile();

  // Just because a file with a matching name was found and it was an actual
  // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
  // must match the GUID specified in the TypeServer2 record.
  Expected<InfoStream &> expectedInfo = Pdb.getPDBInfoStream();
  if (!expectedInfo || expectedInfo->getGuid() != TS.getGuid())
    return createStringError(errc::invalid_argument, "signature_out_of_date");

  // The reader needs to switch to a type server, to process the types from
  // the server. We need to keep the original input source, as reading other
  // sections will require the input associated with the loaded object file.
  TypeServer = std::make_shared<InputFile>(&Pdb);
  LogicalVisitor.setInput(TypeServer);

  LazyRandomTypeCollection &Types = types();
  LazyRandomTypeCollection &Ids = ids();
  if (Error Err = traverseTypes(Pdb, Types, Ids))
    return Err;

  return Error::success();
}

Error LVCodeViewReader::loadPrecompiledObject(PrecompRecord &Precomp,
                                              CVTypeArray &CVTypesObj) {
  LLVM_DEBUG({
    W.printHex("Count", Precomp.getTypesCount());
    W.printHex("Signature", Precomp.getSignature());
    W.printString("PrecompFile", Precomp.getPrecompFilePath());
  });

  SmallString<128> ServerName(Precomp.getPrecompFilePath());
  BuffOrErr = MemoryBuffer::getFile(ServerName);
  if (BuffOrErr.getError()) {
    // The server name does not exist. Try in the directory as the input file.
    ServerName = createAlternativePath(ServerName);
    if (BuffOrErr.getError()) {
      // For the error message, use the original type server name.
      return createStringError(errc::bad_file_descriptor,
                               "File '%s' does not exist.",
                               Precomp.getPrecompFilePath().str().c_str());
    }
  }
  MemBuffer = std::move(BuffOrErr.get());

  Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(*MemBuffer);
  if (errorToErrorCode(BinOrErr.takeError()))
    return createStringError(errc::not_supported,
                             "Binary object format in '%s' is not supported.",
                             ServerName.c_str());

  Binary &BinaryObj = *BinOrErr.get();
  if (!BinaryObj.isCOFF())
    return createStringError(errc::not_supported, "'%s' is not a COFF object.",
                             ServerName.c_str());

  Builder = std::make_unique<AppendingTypeTableBuilder>(BuilderAllocator);

  // The MSVC precompiled header object file, should contain just a single
  // ".debug$P" section.
  COFFObjectFile &Obj = *cast<COFFObjectFile>(&BinaryObj);
  for (const SectionRef &Section : Obj.sections()) {
    Expected<StringRef> SectionNameOrErr = Section.getName();
    if (!SectionNameOrErr)
      return SectionNameOrErr.takeError();
    if (*SectionNameOrErr == ".debug$P") {
      Expected<StringRef> DataOrErr = Section.getContents();
      if (!DataOrErr)
        return DataOrErr.takeError();
      uint32_t Magic;
      if (Error Err = consume(*DataOrErr, Magic))
        return Err;
      if (Magic != COFF::DEBUG_SECTION_MAGIC)
        return errorCodeToError(object_error::parse_failed);

      ReaderPrecomp = std::make_unique<BinaryStreamReader>(
          *DataOrErr, llvm::endianness::little);
      cantFail(
          ReaderPrecomp->readArray(CVTypesPrecomp, ReaderPrecomp->getLength()));

      // Append all the type records up to the LF_ENDPRECOMP marker and
      // check if the signatures match.
      for (const CVType &Type : CVTypesPrecomp) {
        ArrayRef<uint8_t> TypeData = Type.data();
        if (Type.kind() == LF_ENDPRECOMP) {
          EndPrecompRecord EndPrecomp = cantFail(
              TypeDeserializer::deserializeAs<EndPrecompRecord>(TypeData));
          if (Precomp.getSignature() != EndPrecomp.getSignature())
            return createStringError(errc::invalid_argument, "no matching pch");
          break;
        }
        Builder->insertRecordBytes(TypeData);
      }
      // Done processing .debug$P, break out of section loop.
      break;
    }
  }

  // Append all the type records, skipping the first record which is the
  // reference to the precompiled header object information.
  for (const CVType &Type : CVTypesObj) {
    ArrayRef<uint8_t> TypeData = Type.data();
    if (Type.kind() != LF_PRECOMP)
      Builder->insertRecordBytes(TypeData);
  }

  // Set up a type stream that refers to the added type records.
  Builder->ForEachRecord(
      [&](TypeIndex TI, const CVType &Type) { TypeArray.push_back(Type); });

  ItemStream =
      std::make_unique<BinaryItemStream<CVType>>(llvm::endianness::little);
  ItemStream->setItems(TypeArray);
  TypeStream.setUnderlyingStream(*ItemStream);

  PrecompHeader =
      std::make_shared<LazyRandomTypeCollection>(TypeStream, TypeArray.size());

  // Change the original input source to use the collected type records.
  LogicalVisitor.setInput(PrecompHeader);

  LazyRandomTypeCollection &Types = types();
  LazyRandomTypeCollection &Ids = ids();
  LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
                    LogicalVisitor.getShared());
  return visitTypeStream(Types, TDV);
}

Error LVCodeViewReader::traverseTypeSection(StringRef SectionName,
                                            const SectionRef &Section) {
  LLVM_DEBUG({
    ListScope D(W, "CodeViewTypes");
    W.printNumber("Section", SectionName, getObj().getSectionID(Section));
  });

  Expected<StringRef> DataOrErr = Section.getContents();
  if (!DataOrErr)
    return DataOrErr.takeError();
  uint32_t Magic;
  if (Error Err = consume(*DataOrErr, Magic))
    return Err;
  if (Magic != COFF::DEBUG_SECTION_MAGIC)
    return errorCodeToError(object_error::parse_failed);

  // Get the first type record. It will indicate if this object uses a type
  // server (/Zi) or a PCH file (/Yu).
  CVTypeArray CVTypes;
  BinaryStreamReader Reader(*DataOrErr, llvm::endianness::little);
  cantFail(Reader.readArray(CVTypes, Reader.getLength()));
  CVTypeArray::Iterator FirstType = CVTypes.begin();

  // The object was compiled with /Zi. It uses types from a type server PDB.
  if (FirstType->kind() == LF_TYPESERVER2) {
    TypeServer2Record TS = cantFail(
        TypeDeserializer::deserializeAs<TypeServer2Record>(FirstType->data()));
    return loadTypeServer(TS);
  }

  // The object was compiled with /Yc or /Yu. It uses types from another
  // object file with a matching signature.
  if (FirstType->kind() == LF_PRECOMP) {
    PrecompRecord Precomp = cantFail(
        TypeDeserializer::deserializeAs<PrecompRecord>(FirstType->data()));
    return loadPrecompiledObject(Precomp, CVTypes);
  }

  LazyRandomTypeCollection &Types = types();
  LazyRandomTypeCollection &Ids = ids();
  Types.reset(*DataOrErr, 100);
  LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamTPI,
                    LogicalVisitor.getShared());
  return visitTypeStream(Types, TDV);
}

Error LVCodeViewReader::traverseTypes(PDBFile &Pdb,
                                      LazyRandomTypeCollection &Types,
                                      LazyRandomTypeCollection &Ids) {
  // Traverse types (TPI and IPI).
  auto VisitTypes = [&](LazyRandomTypeCollection &Types,
                        LazyRandomTypeCollection &Ids,
                        SpecialStream StreamIdx) -> Error {
    LVTypeVisitor TDV(W, &LogicalVisitor, Types, Ids, StreamIdx,
                      LogicalVisitor.getShared());
    return visitTypeStream(Types, TDV);
  };

  Expected<TpiStream &> StreamTpiOrErr = Pdb.getPDBTpiStream();
  if (!StreamTpiOrErr)
    return StreamTpiOrErr.takeError();
  TpiStream &StreamTpi = *StreamTpiOrErr;
  StreamTpi.buildHashMap();
  LLVM_DEBUG({
    W.getOStream() << formatv("Showing {0:N} TPI records\n",
                              StreamTpi.getNumTypeRecords());
  });
  if (Error Err = VisitTypes(Types, Ids, StreamTPI))
    return Err;

  Expected<TpiStream &> StreamIpiOrErr = Pdb.getPDBIpiStream();
  if (!StreamIpiOrErr)
    return StreamIpiOrErr.takeError();
  TpiStream &StreamIpi = *StreamIpiOrErr;
  StreamIpi.buildHashMap();
  LLVM_DEBUG({
    W.getOStream() << formatv("Showing {0:N} IPI records\n",
                              StreamIpi.getNumTypeRecords());
  });
  return VisitTypes(Ids, Ids, StreamIPI);
}

Error LVCodeViewReader::traverseSymbolsSubsection(StringRef Subsection,
                                                  const SectionRef &Section,
                                                  StringRef SectionContents) {
  ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),
                               Subsection.bytes_end());
  LVSymbolVisitorDelegate VisitorDelegate(this, Section, &getObj(),
                                          SectionContents);
  CVSymbolArray Symbols;
  BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
  if (Error E = Reader.readArray(Symbols, Reader.getLength()))
    return createStringError(errorToErrorCode(std::move(E)), getFileName());

  LazyRandomTypeCollection &Types = types();
  LazyRandomTypeCollection &Ids = ids();
  SymbolVisitorCallbackPipeline Pipeline;
  SymbolDeserializer Deserializer(&VisitorDelegate,
                                  CodeViewContainer::ObjectFile);
  // As we are processing a COFF format, use TPI as IPI, so the generic code
  // to process the CodeView format does not contain any additional checks.
  LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids,
                            &VisitorDelegate, LogicalVisitor.getShared());

  Pipeline.addCallbackToPipeline(Deserializer);
  Pipeline.addCallbackToPipeline(Traverser);
  CVSymbolVisitor Visitor(Pipeline);
  return Visitor.visitSymbolStream(Symbols);
}

Error LVCodeViewReader::traverseSymbolSection(StringRef SectionName,
                                              const SectionRef &Section) {
  LLVM_DEBUG({
    ListScope D(W, "CodeViewDebugInfo");
    W.printNumber("Section", SectionName, getObj().getSectionID(Section));
  });

  Expected<StringRef> SectionOrErr = Section.getContents();
  if (!SectionOrErr)
    return SectionOrErr.takeError();
  StringRef SectionContents = *SectionOrErr;
  StringRef Data = SectionContents;

  SmallVector<StringRef, 10> SymbolNames;
  StringMap<StringRef> FunctionLineTables;

  uint32_t Magic;
  if (Error E = consume(Data, Magic))
    return createStringError(errorToErrorCode(std::move(E)), getFileName());

  if (Magic != COFF::DEBUG_SECTION_MAGIC)
    return createStringError(object_error::parse_failed, getFileName());

  BinaryStreamReader FSReader(Data, llvm::endianness::little);
  if (Error Err = initializeFileAndStringTables(FSReader))
    return Err;

  while (!Data.empty()) {
    // The section consists of a number of subsection in the following format:
    // |SubSectionType|SubSectionSize|Contents...|
    uint32_t SubType, SubSectionSize;
    if (Error E = consume(Data, SubType))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());
    if (Error E = consume(Data, SubSectionSize))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());

    // Process the subsection as normal even if the ignore bit is set.
    SubType &= ~SubsectionIgnoreFlag;

    // Get the contents of the subsection.
    if (SubSectionSize > Data.size())
      return createStringError(object_error::parse_failed, getFileName());
    StringRef Contents = Data.substr(0, SubSectionSize);

    // Add SubSectionSize to the current offset and align that offset
    // to find the next subsection.
    size_t SectionOffset = Data.data() - SectionContents.data();
    size_t NextOffset = SectionOffset + SubSectionSize;
    NextOffset = alignTo(NextOffset, 4);
    if (NextOffset > SectionContents.size())
      return createStringError(object_error::parse_failed, getFileName());
    Data = SectionContents.drop_front(NextOffset);

    switch (DebugSubsectionKind(SubType)) {
    case DebugSubsectionKind::Symbols:
      if (Error Err =
              traverseSymbolsSubsection(Contents, Section, SectionContents))
        return Err;
      break;

    case DebugSubsectionKind::InlineeLines:
      if (Error Err = traverseInlineeLines(Contents))
        return Err;
      break;

    case DebugSubsectionKind::Lines:
      // Holds a PC to file:line table. Some data to parse this subsection
      // is stored in the other subsections, so just check sanity and store
      // the pointers for deferred processing.

      // Collect function and ranges only if we need to print logical lines.
      if (options().getGeneralCollectRanges()) {

        if (SubSectionSize < 12) {
          // There should be at least three words to store two function
          // relocations and size of the code.
          return createStringError(object_error::parse_failed, getFileName());
        }

        StringRef SymbolName;
        if (Error Err = resolveSymbolName(getObj().getCOFFSection(Section),
                                          SectionOffset, SymbolName))
          return createStringError(errorToErrorCode(std::move(Err)),
                                   getFileName());

        LLVM_DEBUG({ W.printString("Symbol Name", SymbolName); });
        if (FunctionLineTables.count(SymbolName) != 0) {
          // Saw debug info for this function already?
          return createStringError(object_error::parse_failed, getFileName());
        }

        FunctionLineTables[SymbolName] = Contents;
        SymbolNames.push_back(SymbolName);
      }
      break;

    // Do nothing for unrecognized subsections.
    default:
      break;
    }
    W.flush();
  }

  // Traverse the line tables now that we've read all the subsections and
  // know all the required information.
  for (StringRef SymbolName : SymbolNames) {
    LLVM_DEBUG({
      ListScope S(W, "FunctionLineTable");
      W.printString("Symbol Name", SymbolName);
    });

    BinaryStreamReader Reader(FunctionLineTables[SymbolName],
                              llvm::endianness::little);

    DebugLinesSubsectionRef Lines;
    if (Error E = Lines.initialize(Reader))
      return createStringError(errorToErrorCode(std::move(E)), getFileName());

    // Find the associated symbol table information.
    LVSymbolTableEntry SymbolTableEntry = getSymbolTableEntry(SymbolName);
    LVScope *Function = SymbolTableEntry.Scope;
    if (!Function)
      continue;

    LVAddress Addendum = SymbolTableEntry.Address;
    LVSectionIndex SectionIndex = SymbolTableEntry.SectionIndex;

    // The given scope represents the function that contains the line numbers.
    // Collect all generated debug lines associated with the function.
    CULines.clear();

    // For the given scope, collect all scopes ranges.
    LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
    ScopesWithRanges->clear();
    Function->getRanges(*ScopesWithRanges);
    ScopesWithRanges->sort();

    uint16_t Segment = Lines.header()->RelocSegment;
    uint32_t Begin = Lines.header()->RelocOffset;
    uint32_t Size = Lines.header()->CodeSize;
    for (const LineColumnEntry &Block : Lines)
      if (Error Err = createLines(Block.LineNumbers, Addendum, Segment, Begin,
                                  Size, Block.NameIndex))
        return Err;

    // Include lines from any inlined functions within the current function.
    includeInlineeLines(SectionIndex, Function);

    if (Error Err = createInstructions(Function, SectionIndex))
      return Err;

    processLines(&CULines, SectionIndex, Function);
  }

  return Error::success();
}

void LVCodeViewReader::sortScopes() { Root->sort(); }

void LVCodeViewReader::print(raw_ostream &OS) const {
  LLVM_DEBUG(dbgs() << "CreateReaders\n");
}

void LVCodeViewReader::mapRangeAddress(const ObjectFile &Obj,
                                       const SectionRef &Section,
                                       bool IsComdat) {
  if (!Obj.isCOFF())
    return;

  const COFFObjectFile *Object = cast<COFFObjectFile>(&Obj);

  for (const SymbolRef &Sym : Object->symbols()) {
    if (!Section.containsSymbol(Sym))
      continue;

    COFFSymbolRef Symbol = Object->getCOFFSymbol(Sym);
    if (Symbol.getComplexType() != llvm::COFF::IMAGE_SYM_DTYPE_FUNCTION)
      continue;

    StringRef SymbolName;
    Expected<StringRef> SymNameOrErr = Object->getSymbolName(Symbol);
    if (!SymNameOrErr) {
      W.startLine() << "Invalid symbol name: " << Symbol.getSectionNumber()
                    << "\n";
      consumeError(SymNameOrErr.takeError());
      continue;
    }
    SymbolName = *SymNameOrErr;

    LLVM_DEBUG({
      Expected<const coff_section *> SectionOrErr =
          Object->getSection(Symbol.getSectionNumber());
      if (!SectionOrErr) {
        W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()
                      << "\n";
        consumeError(SectionOrErr.takeError());
        return;
      }
      W.printNumber("Section #", Symbol.getSectionNumber());
      W.printString("Name", SymbolName);
      W.printHex("Value", Symbol.getValue());
    });

    // Record the symbol name (linkage) and its loading address.
    addToSymbolTable(SymbolName, Symbol.getValue(), Symbol.getSectionNumber(),
                     IsComdat);
  }
}

Error LVCodeViewReader::createScopes(COFFObjectFile &Obj) {
  if (Error Err = loadTargetInfo(Obj))
    return Err;

  // Initialization required when processing a COFF file:
  // Cache the symbols relocations.
  // Create a mapping for virtual addresses.
  // Get the functions entry points.
  cacheRelocations();
  mapVirtualAddress(Obj);

  for (const SectionRef &Section : Obj.sections()) {
    Expected<StringRef> SectionNameOrErr = Section.getName();
    if (!SectionNameOrErr)
      return SectionNameOrErr.takeError();
    // .debug$T is a standard CodeView type section, while .debug$P is the
    // same format but used for MSVC precompiled header object files.
    if (*SectionNameOrErr == ".debug$T" || *SectionNameOrErr == ".debug$P")
      if (Error Err = traverseTypeSection(*SectionNameOrErr, Section))
        return Err;
  }

  // Process collected namespaces.
  LogicalVisitor.processNamespaces();

  for (const SectionRef &Section : Obj.sections()) {
    Expected<StringRef> SectionNameOrErr = Section.getName();
    if (!SectionNameOrErr)
      return SectionNameOrErr.takeError();
    if (*SectionNameOrErr == ".debug$S")
      if (Error Err = traverseSymbolSection(*SectionNameOrErr, Section))
        return Err;
  }

  // Check if we have to close the Compile Unit scope.
  LogicalVisitor.closeScope();

  // Traverse the strings recorded and transform them into filenames.
  LogicalVisitor.processFiles();

  // Process collected element lines.
  LogicalVisitor.processLines();

  // Translate composite names into a single component.
  Root->transformScopedName();
  return Error::success();
}

Error LVCodeViewReader::createScopes(PDBFile &Pdb) {
  if (Error Err = loadTargetInfo(Pdb))
    return Err;

  if (!Pdb.hasPDBTpiStream() || !Pdb.hasPDBDbiStream())
    return Error::success();

  // Open the executable associated with the PDB file and get the section
  // addresses used to calculate linear addresses for CodeView Symbols.
  if (!ExePath.empty()) {
    ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
        MemoryBuffer::getFileOrSTDIN(ExePath);
    if (BuffOrErr.getError()) {
      return createStringError(errc::bad_file_descriptor,
                               "File '%s' does not exist.", ExePath.c_str());
    }
    BinaryBuffer = std::move(BuffOrErr.get());

    // Check if the buffer corresponds to a PECOFF executable.
    assert(identify_magic(BinaryBuffer->getBuffer()) ==
               file_magic::pecoff_executable &&
           "Invalid PECOFF executable file.");

    Expected<std::unique_ptr<Binary>> BinOrErr =
        createBinary(BinaryBuffer->getMemBufferRef());
    if (errorToErrorCode(BinOrErr.takeError())) {
      return createStringError(errc::not_supported,
                               "Binary object format in '%s' is not supported.",
                               ExePath.c_str());
    }
    BinaryExecutable = std::move(*BinOrErr);
    if (COFFObjectFile *COFFObject =
            dyn_cast<COFFObjectFile>(BinaryExecutable.get()))
      mapVirtualAddress(*COFFObject);
  }

  // In order to generate a full logical view, we have to traverse both
  // streams TPI and IPI if they are present. The following table gives
  // the stream where a specified type is located. If the IPI stream is
  // not present, all the types are located in the TPI stream.
  //
  // TPI Stream:
  //   LF_POINTER   LF_MODIFIER     LF_PROCEDURE    LF_MFUNCTION
  //   LF_LABEL     LF_ARGLIST      LF_FIELDLIST    LF_ARRAY
  //   LF_CLASS     LF_STRUCTURE    LF_INTERFACE    LF_UNION
  //   LF_ENUM      LF_TYPESERVER2  LF_VFTABLE      LF_VTSHAPE
  //   LF_BITFIELD  LF_METHODLIST   LF_PRECOMP      LF_ENDPRECOMP
  //
  // IPI stream:
  //   LF_FUNC_ID           LF_MFUNC_ID   LF_BUILDINFO
  //   LF_SUBSTR_LIST       LF_STRING_ID  LF_UDT_SRC_LINE
  //   LF_UDT_MOD_SRC_LINE

  LazyRandomTypeCollection &Types = types();
  LazyRandomTypeCollection &Ids = ids();
  if (Error Err = traverseTypes(Pdb, Types, Ids))
    return Err;

  // Process collected namespaces.
  LogicalVisitor.processNamespaces();

  LLVM_DEBUG({ W.getOStream() << "Traversing inlined lines\n"; });

  auto VisitInlineeLines = [&](int32_t Modi, const SymbolGroup &SG,
                               DebugInlineeLinesSubsectionRef &Lines) -> Error {
    return collectInlineeInfo(Lines, &SG);
  };

  FilterOptions Filters = {};
  LinePrinter Printer(/*Indent=*/2, false, nulls(), Filters);
  const PrintScope HeaderScope(Printer, /*IndentLevel=*/2);
  if (Error Err = iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
          Input, HeaderScope, VisitInlineeLines))
    return Err;

  // Traverse global symbols.
  LLVM_DEBUG({ W.getOStream() << "Traversing global symbols\n"; });
  if (Pdb.hasPDBGlobalsStream()) {
    Expected<GlobalsStream &> GlobalsOrErr = Pdb.getPDBGlobalsStream();
    if (!GlobalsOrErr)
      return GlobalsOrErr.takeError();
    GlobalsStream &Globals = *GlobalsOrErr;
    const GSIHashTable &Table = Globals.getGlobalsTable();
    Expected<SymbolStream &> ExpectedSyms = Pdb.getPDBSymbolStream();
    if (ExpectedSyms) {

      SymbolVisitorCallbackPipeline Pipeline;
      SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
      LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
                                LogicalVisitor.getShared());

      // As the global symbols do not have an associated Compile Unit, create
      // one, as the container for all global symbols.
      RecordPrefix Prefix(SymbolKind::S_COMPILE3);
      CVSymbol Symbol(&Prefix, sizeof(Prefix));
      uint32_t Offset = 0;
      if (Error Err = Traverser.visitSymbolBegin(Symbol, Offset))
        consumeError(std::move(Err));
      else {
        // The CodeView compile unit containing the global symbols does not
        // have a name; generate one using its parent name (object filename)
        // follow by the '_global' string.
        std::string Name(CompileUnit->getParentScope()->getName());
        CompileUnit->setName(Name.append("_global"));

        Pipeline.addCallbackToPipeline(Deserializer);
        Pipeline.addCallbackToPipeline(Traverser);
        CVSymbolVisitor Visitor(Pipeline);

        BinaryStreamRef SymStream =
            ExpectedSyms->getSymbolArray().getUnderlyingStream();
        for (uint32_t PubSymOff : Table) {
          Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
          if (Sym) {
            if (Error Err = Visitor.visitSymbolRecord(*Sym, PubSymOff))
              return createStringError(errorToErrorCode(std::move(Err)),
                                       getFileName());
          } else {
            consumeError(Sym.takeError());
          }
        }
      }

      LogicalVisitor.closeScope();
    } else {
      consumeError(ExpectedSyms.takeError());
    }
  }

  // Traverse symbols (DBI).
  LLVM_DEBUG({ W.getOStream() << "Traversing symbol groups\n"; });

  auto VisitSymbolGroup = [&](uint32_t Modi, const SymbolGroup &SG) -> Error {
    Expected<ModuleDebugStreamRef> ExpectedModS =
        getModuleDebugStream(Pdb, Modi);
    if (ExpectedModS) {
      ModuleDebugStreamRef &ModS = *ExpectedModS;

      LLVM_DEBUG({
        W.getOStream() << formatv("Traversing Group: Mod {0:4}\n", Modi);
      });

      SymbolVisitorCallbackPipeline Pipeline;
      SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
      LVSymbolVisitor Traverser(this, W, &LogicalVisitor, Types, Ids, nullptr,
                                LogicalVisitor.getShared());

      Pipeline.addCallbackToPipeline(Deserializer);
      Pipeline.addCallbackToPipeline(Traverser);
      CVSymbolVisitor Visitor(Pipeline);
      BinarySubstreamRef SS = ModS.getSymbolsSubstream();
      if (Error Err =
              Visitor.visitSymbolStream(ModS.getSymbolArray(), SS.Offset))
        return createStringError(errorToErrorCode(std::move(Err)),
                                 getFileName());
    } else {
      // If the module stream does not exist, it is not an error condition.
      consumeError(ExpectedModS.takeError());
    }

    return Error::success();
  };

  if (Error Err = iterateSymbolGroups(Input, HeaderScope, VisitSymbolGroup))
    return Err;

  // At this stage, the logical view contains all scopes, symbols and types.
  // For PDBs we can use the module id, to access its specific compile unit.
  // The line record addresses has been already resolved, so we can apply the
  // flow as when processing DWARF.

  LLVM_DEBUG({ W.getOStream() << "Traversing lines\n"; });

  // Record all line records for a Compile Unit.
  CULines.clear();

  auto VisitDebugLines = [this](int32_t Modi, const SymbolGroup &SG,
                                DebugLinesSubsectionRef &Lines) -> Error {
    if (!options().getPrintLines())
      return Error::success();

    uint16_t Segment = Lines.header()->RelocSegment;
    uint32_t Begin = Lines.header()->RelocOffset;
    uint32_t Size = Lines.header()->CodeSize;

    LLVM_DEBUG({ W.getOStream() << formatv("Modi = {0}\n", Modi); });

    // We have line information for a new module; finish processing the
    // collected information for the current module. Once it is done, start
    // recording the line information for the new module.
    if (CurrentModule != Modi) {
      if (Error Err = processModule())
        return Err;
      CULines.clear();
      CurrentModule = Modi;
    }

    for (const LineColumnEntry &Block : Lines)
      if (Error Err = createLines(Block.LineNumbers, /*Addendum=*/0, Segment,
                                  Begin, Size, Block.NameIndex, &SG))
        return Err;

    return Error::success();
  };

  if (Error Err = iterateModuleSubsections<DebugLinesSubsectionRef>(
          Input, HeaderScope, VisitDebugLines))
    return Err;

  // Check if we have to close the Compile Unit scope.
  LogicalVisitor.closeScope();

  // Process collected element lines.
  LogicalVisitor.processLines();

  // Translate composite names into a single component.
  Root->transformScopedName();
  return Error::success();
}

Error LVCodeViewReader::processModule() {
  if (LVScope *Scope = getScopeForModule(CurrentModule)) {
    CompileUnit = static_cast<LVScopeCompileUnit *>(Scope);

    LLVM_DEBUG({ dbgs() << "Processing Scope: " << Scope->getName() << "\n"; });

    // For the given compile unit, collect all scopes ranges.
    // For a complete ranges and lines mapping, the logical view support
    // needs for the compile unit to have a low and high pc values. We
    // can traverse the 'Modules' section and get the information for the
    // specific module. Another option, is from all the ranges collected
    // to take the first and last values.
    LVSectionIndex SectionIndex = DotTextSectionIndex;
    LVRange *ScopesWithRanges = getSectionRanges(SectionIndex);
    ScopesWithRanges->clear();
    CompileUnit->getRanges(*ScopesWithRanges);
    if (!ScopesWithRanges->empty())
      CompileUnit->addObject(ScopesWithRanges->getLower(),
                             ScopesWithRanges->getUpper());
    ScopesWithRanges->sort();

    if (Error Err = createInstructions())
      return Err;

    // Include lines from any inlined functions within the current function.
    includeInlineeLines(SectionIndex, Scope);

    processLines(&CULines, SectionIndex, nullptr);
  }

  return Error::success();
}

// In order to create the scopes, the CodeView Reader will:
// = Traverse the TPI/IPI stream (Type visitor):
// Collect forward references, scoped names, type indexes that will represent
// a logical element, strings, line records, linkage names.
// = Traverse the symbols section (Symbol visitor):
// Create the scopes tree and creates the required logical elements, by
// using the collected indexes from the type visitor.
Error LVCodeViewReader::createScopes() {
  LLVM_DEBUG({
    W.startLine() << "\n";
    W.printString("File", getFileName().str());
    W.printString("Exe", ExePath);
    W.printString("Format", FileFormatName);
  });

  if (Error Err = LVReader::createScopes())
    return Err;

  LogicalVisitor.setRoot(Root);

  if (isObj()) {
    if (Error Err = createScopes(getObj()))
      return Err;
  } else {
    if (Error Err = createScopes(getPdb()))
      return Err;
  }

  return Error::success();
}

Error LVCodeViewReader::loadTargetInfo(const ObjectFile &Obj) {
  // Detect the architecture from the object file. We usually don't need OS
  // info to lookup a target and create register info.
  Triple TT;
  TT.setArch(Triple::ArchType(Obj.getArch()));
  TT.setVendor(Triple::UnknownVendor);
  TT.setOS(Triple::UnknownOS);

  // Features to be passed to target/subtarget
  Expected<SubtargetFeatures> Features = Obj.getFeatures();
  SubtargetFeatures FeaturesValue;
  if (!Features) {
    consumeError(Features.takeError());
    FeaturesValue = SubtargetFeatures();
  }
  FeaturesValue = *Features;
  return loadGenericTargetInfo(TT.str(), FeaturesValue.getString());
}

Error LVCodeViewReader::loadTargetInfo(const PDBFile &Pdb) {
  Triple TT;
  TT.setArch(Triple::ArchType::x86_64);
  TT.setVendor(Triple::UnknownVendor);
  TT.setOS(Triple::Win32);

  StringRef TheFeature = "";

  return loadGenericTargetInfo(TT.str(), TheFeature);
}

std::string LVCodeViewReader::getRegisterName(LVSmall Opcode,
                                              ArrayRef<uint64_t> Operands) {
  // Get Compilation Unit CPU Type.
  CPUType CPU = getCompileUnitCPUType();
  // For CodeView the register always is in Operands[0];
  RegisterId Register = (RegisterId(Operands[0]));
  return formatRegisterId(Register, CPU);
}
