//===-- 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);

    auto &RM = RelocMap[CoffSection];
    llvm::append_range(RM, Section.relocations());

    // Sort relocations by address.
    llvm::sort(RM, [](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.try_emplace(SymbolName, Contents).second) {
          // Saw debug info for this function already?
          return createStringError(object_error::parse_failed, getFileName());
        }

        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;

  StringRef CPU;
  if (auto OptCPU = Obj.tryGetCPUName())
    CPU = *OptCPU;

  return loadGenericTargetInfo(TT.str(), FeaturesValue.getString(), CPU);
}

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

  StringRef TheFeature = "";
  StringRef TheCPU = "";

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

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);
}
