//===-- 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/EnumTables.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/LogicalView/Core/LVSymbol.h"
#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
#include "llvm/DebugInfo/PDB/GenericError.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/Demangle/Demangle.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 StringRef::npos != Name.find(String);
  };
  auto Starts = [=](const char *Pattern) -> bool {
    return Name.startswith(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::support::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, support::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, support::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::support::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, support::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::support::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, support::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], support::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,
                                              uint64_t Operands[2]) {
  // 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);
}
