//===- PDB.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
//
//===----------------------------------------------------------------------===//

#include "PDB.h"
#include "Chunks.h"
#include "Config.h"
#include "DebugTypes.h"
#include "Driver.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "TypeMerger.h"
#include "Writer.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Timer.h"
#include "lld/Common/Threads.h"
#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/CVDebugRecord.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/JamCRC.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ScopedPrinter.h"
#include <memory>

using namespace lld;
using namespace lld::coff;
using namespace llvm;
using namespace llvm::codeview;

using llvm::object::coff_section;

static ExitOnError ExitOnErr;

static Timer TotalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root());

static Timer AddObjectsTimer("Add Objects", TotalPdbLinkTimer);
static Timer TypeMergingTimer("Type Merging", AddObjectsTimer);
static Timer SymbolMergingTimer("Symbol Merging", AddObjectsTimer);
static Timer GlobalsLayoutTimer("Globals Stream Layout", TotalPdbLinkTimer);
static Timer TpiStreamLayoutTimer("TPI Stream Layout", TotalPdbLinkTimer);
static Timer DiskCommitTimer("Commit to Disk", TotalPdbLinkTimer);

namespace {
class DebugSHandler;

class PDBLinker {
  friend DebugSHandler;

public:
  PDBLinker(SymbolTable *Symtab)
      : Alloc(), Symtab(Symtab), Builder(Alloc), TMerger(Alloc) {
    // This isn't strictly necessary, but link.exe usually puts an empty string
    // as the first "valid" string in the string table, so we do the same in
    // order to maintain as much byte-for-byte compatibility as possible.
    PDBStrTab.insert("");
  }

  /// Emit the basic PDB structure: initial streams, headers, etc.
  void initialize(llvm::codeview::DebugInfo *BuildId);

  /// Add natvis files specified on the command line.
  void addNatvisFiles();

  /// Link CodeView from each object file in the symbol table into the PDB.
  void addObjectsToPDB();

  /// Link info for each import file in the symbol table into the PDB.
  void addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections);

  /// Link CodeView from a single object file into the target (output) PDB.
  /// When a precompiled headers object is linked, its TPI map might be provided
  /// externally.
  void addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap = nullptr);

  /// Produce a mapping from the type and item indices used in the object
  /// file to those in the destination PDB.
  ///
  /// If the object file uses a type server PDB (compiled with /Zi), merge TPI
  /// and IPI from the type server PDB and return a map for it. Each unique type
  /// server PDB is merged at most once, so this may return an existing index
  /// mapping.
  ///
  /// If the object does not use a type server PDB (compiled with /Z7), we merge
  /// all the type and item records from the .debug$S stream and fill in the
  /// caller-provided ObjectIndexMap.
  Expected<const CVIndexMap &> mergeDebugT(ObjFile *File,
                                           CVIndexMap *ObjectIndexMap);

  /// Reads and makes available a PDB.
  Expected<const CVIndexMap &> maybeMergeTypeServerPDB(ObjFile *File);

  /// Merges a precompiled headers TPI map into the current TPI map. The
  /// precompiled headers object will also be loaded and remapped in the
  /// process.
  Error mergeInPrecompHeaderObj(ObjFile *File, CVIndexMap *ObjectIndexMap);

  /// Reads and makes available a precompiled headers object.
  ///
  /// This is a requirement for objects compiled with cl.exe /Yu. In that
  /// case, the referenced object (which was compiled with /Yc) has to be loaded
  /// first. This is mainly because the current object's TPI stream has external
  /// references to the precompiled headers object.
  ///
  /// If the precompiled headers object was already loaded, this function will
  /// simply return its (remapped) TPI map.
  Expected<const CVIndexMap &> aquirePrecompObj(ObjFile *File);

  /// Adds a precompiled headers object signature -> TPI mapping.
  std::pair<CVIndexMap &, bool /*already there*/>
  registerPrecompiledHeaders(uint32_t Signature);

  void mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap,
                          std::vector<ulittle32_t *> &StringTableRefs,
                          BinaryStreamRef SymData);

  /// Add the section map and section contributions to the PDB.
  void addSections(ArrayRef<OutputSection *> OutputSections,
                   ArrayRef<uint8_t> SectionTable);

  /// Write the PDB to disk and store the Guid generated for it in *Guid.
  void commit(codeview::GUID *Guid);

  // Print statistics regarding the final PDB
  void printStats();

private:
  BumpPtrAllocator Alloc;

  SymbolTable *Symtab;

  pdb::PDBFileBuilder Builder;

  TypeMerger TMerger;

  /// PDBs use a single global string table for filenames in the file checksum
  /// table.
  DebugStringTableSubsection PDBStrTab;

  llvm::SmallString<128> NativePath;

  /// A list of other PDBs which are loaded during the linking process and which
  /// we need to keep around since the linking operation may reference pointers
  /// inside of these PDBs.
  llvm::SmallVector<std::unique_ptr<pdb::NativeSession>, 2> LoadedPDBs;

  std::vector<pdb::SecMapEntry> SectionMap;

  /// Type index mappings of type server PDBs that we've loaded so far.
  std::map<codeview::GUID, CVIndexMap> TypeServerIndexMappings;

  /// Type index mappings of precompiled objects type map that we've loaded so
  /// far.
  std::map<uint32_t, CVIndexMap> PrecompTypeIndexMappings;

  /// List of TypeServer PDBs which cannot be loaded.
  /// Cached to prevent repeated load attempts.
  std::map<codeview::GUID, std::string> MissingTypeServerPDBs;

  // For statistics
  uint64_t GlobalSymbols = 0;
  uint64_t ModuleSymbols = 0;
  uint64_t PublicSymbols = 0;
};

class DebugSHandler {
  PDBLinker &Linker;

  /// The object file whose .debug$S sections we're processing.
  ObjFile &File;

  /// The result of merging type indices.
  const CVIndexMap &IndexMap;

  /// The DEBUG_S_STRINGTABLE subsection.  These strings are referred to by
  /// index from other records in the .debug$S section.  All of these strings
  /// need to be added to the global PDB string table, and all references to
  /// these strings need to have their indices re-written to refer to the
  /// global PDB string table.
  DebugStringTableSubsectionRef CVStrTab;

  /// The DEBUG_S_FILECHKSMS subsection.  As above, these are referred to
  /// by other records in the .debug$S section and need to be merged into the
  /// PDB.
  DebugChecksumsSubsectionRef Checksums;

  /// The DEBUG_S_FRAMEDATA subsection(s).  There can be more than one of
  /// these and they need not appear in any specific order.  However, they
  /// contain string table references which need to be re-written, so we
  /// collect them all here and re-write them after all subsections have been
  /// discovered and processed.
  std::vector<DebugFrameDataSubsectionRef> NewFpoFrames;

  /// Pointers to raw memory that we determine have string table references
  /// that need to be re-written.  We first process all .debug$S subsections
  /// to ensure that we can handle subsections written in any order, building
  /// up this list as we go.  At the end, we use the string table (which must
  /// have been discovered by now else it is an error) to re-write these
  /// references.
  std::vector<ulittle32_t *> StringTableReferences;

public:
  DebugSHandler(PDBLinker &Linker, ObjFile &File, const CVIndexMap &IndexMap)
      : Linker(Linker), File(File), IndexMap(IndexMap) {}

  void handleDebugS(lld::coff::SectionChunk &DebugS);
  void finish();
};
}

// Visual Studio's debugger requires absolute paths in various places in the
// PDB to work without additional configuration:
// https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box
static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {
  // The default behavior is to produce paths that are valid within the context
  // of the machine that you perform the link on.  If the linker is running on
  // a POSIX system, we will output absolute POSIX paths.  If the linker is
  // running on a Windows system, we will output absolute Windows paths.  If the
  // user desires any other kind of behavior, they should explicitly pass
  // /pdbsourcepath, in which case we will treat the exact string the user
  // passed in as the gospel and not normalize, canonicalize it.
  if (sys::path::is_absolute(FileName, sys::path::Style::windows) ||
      sys::path::is_absolute(FileName, sys::path::Style::posix))
    return;

  // It's not absolute in any path syntax.  Relative paths necessarily refer to
  // the local file system, so we can make it native without ending up with a
  // nonsensical path.
  if (Config->PDBSourcePath.empty()) {
    sys::path::native(FileName);
    sys::fs::make_absolute(FileName);
    return;
  }

  // Try to guess whether /PDBSOURCEPATH is a unix path or a windows path.
  // Since PDB's are more of a Windows thing, we make this conservative and only
  // decide that it's a unix path if we're fairly certain.  Specifically, if
  // it starts with a forward slash.
  SmallString<128> AbsoluteFileName = Config->PDBSourcePath;
  sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/")
                                      ? sys::path::Style::posix
                                      : sys::path::Style::windows;
  sys::path::append(AbsoluteFileName, GuessedStyle, FileName);
  sys::path::native(AbsoluteFileName, GuessedStyle);
  sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle);

  FileName = std::move(AbsoluteFileName);
}

// A COFF .debug$H section is currently a clang extension.  This function checks
// if a .debug$H section is in a format that we expect / understand, so that we
// can ignore any sections which are coincidentally also named .debug$H but do
// not contain a format we recognize.
static bool canUseDebugH(ArrayRef<uint8_t> DebugH) {
  if (DebugH.size() < sizeof(object::debug_h_header))
    return false;
  auto *Header =
      reinterpret_cast<const object::debug_h_header *>(DebugH.data());
  DebugH = DebugH.drop_front(sizeof(object::debug_h_header));
  return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&
         Header->Version == 0 &&
         Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) &&
         (DebugH.size() % 8 == 0);
}

static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *File) {
  SectionChunk *Sec =
      SectionChunk::findByName(File->getDebugChunks(), ".debug$H");
  if (!Sec)
    return llvm::None;
  ArrayRef<uint8_t> Contents = Sec->getContents();
  if (!canUseDebugH(Contents))
    return None;
  return Contents;
}

static ArrayRef<GloballyHashedType>
getHashesFromDebugH(ArrayRef<uint8_t> DebugH) {
  assert(canUseDebugH(DebugH));

  DebugH = DebugH.drop_front(sizeof(object::debug_h_header));
  uint32_t Count = DebugH.size() / sizeof(GloballyHashedType);
  return {reinterpret_cast<const GloballyHashedType *>(DebugH.data()), Count};
}

static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
                        TypeCollection &TypeTable) {
  // Start the TPI or IPI stream header.
  TpiBuilder.setVersionHeader(pdb::PdbTpiV80);

  // Flatten the in memory type table and hash each type.
  TypeTable.ForEachRecord([&](TypeIndex TI, const CVType &Type) {
    auto Hash = pdb::hashTypeRecord(Type);
    if (auto E = Hash.takeError())
      fatal("type hashing error");
    TpiBuilder.addTypeRecord(Type.RecordData, *Hash);
  });
}

Expected<const CVIndexMap &>
PDBLinker::mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap) {
  ScopedTimer T(TypeMergingTimer);

  if (!File->DebugTypesObj)
      return *ObjectIndexMap; // no Types stream

  // Precompiled headers objects need to save the index map for further
  // reference by other objects which use the precompiled headers.
  if (File->DebugTypesObj->Kind == TpiSource::PCH) {
    uint32_t PCHSignature = File->PCHSignature.getValueOr(0);
    if (PCHSignature == 0)
      fatal("No signature found for the precompiled headers OBJ (" +
            File->getName() + ")");

    // When a precompiled headers object comes first on the command-line, we
    // update the mapping here. Otherwise, if an object referencing the
    // precompiled headers object comes first, the mapping is created in
    // aquirePrecompObj(), thus we would skip this block.
    if (!ObjectIndexMap->IsPrecompiledTypeMap) {
      auto R = registerPrecompiledHeaders(PCHSignature);
      if (R.second)
        fatal(
            "A precompiled headers OBJ with the same signature was already "
            "provided! (" +
            File->getName() + ")");

      ObjectIndexMap = &R.first;
    }
  }

  if (File->DebugTypesObj->Kind == TpiSource::UsingPDB) {
    // Look through type servers. If we've already seen this type server,
    // don't merge any type information.
    return maybeMergeTypeServerPDB(File);
  }
  
  CVTypeArray &Types = *File->DebugTypes;

  if (File->DebugTypesObj->Kind == TpiSource::UsingPCH) {
    // This object was compiled with /Yu, so process the corresponding
    // precompiled headers object (/Yc) first. Some type indices in the current
    // object are referencing data in the precompiled headers object, so we need
    // both to be loaded.
    Error E = mergeInPrecompHeaderObj(File, ObjectIndexMap);
    if (E)
      return std::move(E);

    // Drop LF_PRECOMP record from the input stream, as it has been replaced
    // with the precompiled headers Type stream in the mergeInPrecompHeaderObj()
    // call above. Note that we can't just call Types.drop_front(), as we
    // explicitly want to rebase the stream.
    CVTypeArray::Iterator FirstType = Types.begin();
    Types.setUnderlyingStream(
        Types.getUnderlyingStream().drop_front(FirstType->RecordData.size()));
  }

  // Fill in the temporary, caller-provided ObjectIndexMap.
  if (Config->DebugGHashes) {
    ArrayRef<GloballyHashedType> Hashes;
    std::vector<GloballyHashedType> OwnedHashes;
    if (Optional<ArrayRef<uint8_t>> DebugH = getDebugH(File))
      Hashes = getHashesFromDebugH(*DebugH);
    else {
      OwnedHashes = GloballyHashedType::hashTypes(Types);
      Hashes = OwnedHashes;
    }

    if (auto Err = mergeTypeAndIdRecords(
            TMerger.GlobalIDTable, TMerger.GlobalTypeTable,
            ObjectIndexMap->TPIMap, Types, Hashes, File->PCHSignature))
      fatal("codeview::mergeTypeAndIdRecords failed: " +
            toString(std::move(Err)));
  } else {
    if (auto Err = mergeTypeAndIdRecords(TMerger.IDTable, TMerger.TypeTable,
                                         ObjectIndexMap->TPIMap, Types,
                                         File->PCHSignature))
      fatal("codeview::mergeTypeAndIdRecords failed: " +
            toString(std::move(Err)));
  }
  return *ObjectIndexMap;
}

static Expected<std::unique_ptr<pdb::NativeSession>>
tryToLoadPDB(const codeview::GUID &GuidFromObj, StringRef TSPath) {
  // Ensure the file exists before anything else. We want to return ENOENT,
  // "file not found", even if the path points to a removable device (in which
  // case the return message would be EAGAIN, "resource unavailable try again")
  if (!llvm::sys::fs::exists(TSPath))
    return errorCodeToError(std::error_code(ENOENT, std::generic_category()));

  ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(
      TSPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
  if (!MBOrErr)
    return errorCodeToError(MBOrErr.getError());

  std::unique_ptr<pdb::IPDBSession> ThisSession;
  if (auto EC = pdb::NativeSession::createFromPdb(
          MemoryBuffer::getMemBuffer(Driver->takeBuffer(std::move(*MBOrErr)),
                                     /*RequiresNullTerminator=*/false),
          ThisSession))
    return std::move(EC);

  std::unique_ptr<pdb::NativeSession> NS(
      static_cast<pdb::NativeSession *>(ThisSession.release()));
  pdb::PDBFile &File = NS->getPDBFile();
  auto ExpectedInfo = File.getPDBInfoStream();
  // All PDB Files should have an Info stream.
  if (!ExpectedInfo)
    return ExpectedInfo.takeError();

  // 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.
  if (ExpectedInfo->getGuid() != GuidFromObj)
    return make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date);

  return std::move(NS);
}

Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) {
  const TypeServer2Record &TS =
      retrieveDependencyInfo<TypeServer2Record>(File->DebugTypesObj);

  const codeview::GUID &TSId = TS.getGuid();
  StringRef TSPath = TS.getName();

  // First, check if the PDB has previously failed to load.
  auto PrevErr = MissingTypeServerPDBs.find(TSId);
  if (PrevErr != MissingTypeServerPDBs.end())
    return createFileError(
        TSPath,
        make_error<StringError>(PrevErr->second, inconvertibleErrorCode()));

  // Second, check if we already loaded a PDB with this GUID. Return the type
  // index mapping if we have it.
  auto Insertion = TypeServerIndexMappings.insert({TSId, CVIndexMap()});
  CVIndexMap &IndexMap = Insertion.first->second;
  if (!Insertion.second)
    return IndexMap;

  // Mark this map as a type server map.
  IndexMap.IsTypeServerMap = true;

  // Check for a PDB at:
  // 1. The given file path
  // 2. Next to the object file or archive file
  auto ExpectedSession = handleExpected(
      tryToLoadPDB(TSId, TSPath),
      [&]() {
        StringRef LocalPath =
            !File->ParentName.empty() ? File->ParentName : File->getName();
        SmallString<128> Path = sys::path::parent_path(LocalPath);
        // Currently, type server PDBs are only created by cl, which only runs
        // on Windows, so we can assume type server paths are Windows style.
        sys::path::append(
            Path, sys::path::filename(TSPath, sys::path::Style::windows));
        return tryToLoadPDB(TSId, Path);
      },
      [&](std::unique_ptr<ECError> EC) -> Error {
        auto SysErr = EC->convertToErrorCode();
        // Only re-try loading if the previous error was "No such file or
        // directory"
        if (SysErr.category() == std::generic_category() &&
            SysErr.value() == ENOENT)
          return Error::success();
        return Error(std::move(EC));
      });

  if (auto E = ExpectedSession.takeError()) {
    TypeServerIndexMappings.erase(TSId);

    // Flatten the error to a string, for later display, if the error occurs
    // again on the same PDB.
    std::string ErrMsg;
    raw_string_ostream S(ErrMsg);
    S << E;
    MissingTypeServerPDBs.emplace(TSId, S.str());

    return createFileError(TSPath, std::move(E));
  }

  pdb::NativeSession *Session = ExpectedSession->get();

  // Keep a strong reference to this PDB, so that it's safe to hold pointers
  // into the file.
  LoadedPDBs.push_back(std::move(*ExpectedSession));

  auto ExpectedTpi = Session->getPDBFile().getPDBTpiStream();
  if (auto E = ExpectedTpi.takeError())
    fatal("Type server does not have TPI stream: " + toString(std::move(E)));
  auto ExpectedIpi = Session->getPDBFile().getPDBIpiStream();
  if (auto E = ExpectedIpi.takeError())
    fatal("Type server does not have TPI stream: " + toString(std::move(E)));

  if (Config->DebugGHashes) {
    // PDBs do not actually store global hashes, so when merging a type server
    // PDB we have to synthesize global hashes.  To do this, we first synthesize
    // global hashes for the TPI stream, since it is independent, then we
    // synthesize hashes for the IPI stream, using the hashes for the TPI stream
    // as inputs.
    auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray());
    auto IpiHashes =
        GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes);

    Optional<uint32_t> EndPrecomp;
    // Merge TPI first, because the IPI stream will reference type indices.
    if (auto Err =
            mergeTypeRecords(TMerger.GlobalTypeTable, IndexMap.TPIMap,
                             ExpectedTpi->typeArray(), TpiHashes, EndPrecomp))
      fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));

    // Merge IPI.
    if (auto Err = mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap,
                                  IndexMap.IPIMap, ExpectedIpi->typeArray(),
                                  IpiHashes))
      fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
  } else {
    // Merge TPI first, because the IPI stream will reference type indices.
    if (auto Err = mergeTypeRecords(TMerger.TypeTable, IndexMap.TPIMap,
                                    ExpectedTpi->typeArray()))
      fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));

    // Merge IPI.
    if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap,
                                  IndexMap.IPIMap, ExpectedIpi->typeArray()))
      fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
  }

  return IndexMap;
}

Error PDBLinker::mergeInPrecompHeaderObj(ObjFile *File,
                                         CVIndexMap *ObjectIndexMap) {
  const PrecompRecord &Precomp =
      retrieveDependencyInfo<PrecompRecord>(File->DebugTypesObj);

  Expected<const CVIndexMap &> E = aquirePrecompObj(File);
  if (!E)
    return E.takeError();

  const CVIndexMap &PrecompIndexMap = *E;
  assert(PrecompIndexMap.IsPrecompiledTypeMap);

  if (PrecompIndexMap.TPIMap.empty())
    return Error::success();

  assert(Precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex);
  assert(Precomp.getTypesCount() <= PrecompIndexMap.TPIMap.size());
  // Use the previously remapped index map from the precompiled headers.
  ObjectIndexMap->TPIMap.append(PrecompIndexMap.TPIMap.begin(),
                                PrecompIndexMap.TPIMap.begin() +
                                    Precomp.getTypesCount());
  return Error::success();
}

static bool equals_path(StringRef path1, StringRef path2) {
#if defined(_WIN32)
  return path1.equals_lower(path2);
#else
  return path1.equals(path2);
#endif
}

// Find by name an OBJ provided on the command line
static ObjFile *findObjByName(StringRef FileNameOnly) {
  SmallString<128> CurrentPath;

  for (ObjFile *F : ObjFile::Instances) {
    StringRef CurrentFileName = sys::path::filename(F->getName());

    // Compare based solely on the file name (link.exe behavior)
    if (equals_path(CurrentFileName, FileNameOnly))
      return F;
  }
  return nullptr;
}

std::pair<CVIndexMap &, bool /*already there*/>
PDBLinker::registerPrecompiledHeaders(uint32_t Signature) {
  auto Insertion = PrecompTypeIndexMappings.insert({Signature, CVIndexMap()});
  CVIndexMap &IndexMap = Insertion.first->second;
  if (!Insertion.second)
    return {IndexMap, true};
  // Mark this map as a precompiled types map.
  IndexMap.IsPrecompiledTypeMap = true;
  return {IndexMap, false};
}

Expected<const CVIndexMap &> PDBLinker::aquirePrecompObj(ObjFile *File) {
  const PrecompRecord &Precomp =
      retrieveDependencyInfo<PrecompRecord>(File->DebugTypesObj);

  // First, check if we already loaded the precompiled headers object with this
  // signature. Return the type index mapping if we've already seen it.
  auto R = registerPrecompiledHeaders(Precomp.getSignature());
  if (R.second)
    return R.first;

  CVIndexMap &IndexMap = R.first;

  // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP
  // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly,
  // the paths embedded in the OBJs are in the Windows format.
  SmallString<128> PrecompFileName = sys::path::filename(
      Precomp.getPrecompFilePath(), sys::path::Style::windows);

  // link.exe requires that a precompiled headers object must always be provided
  // on the command-line, even if that's not necessary.
  auto PrecompFile = findObjByName(PrecompFileName);
  if (!PrecompFile)
    return createFileError(
        PrecompFileName.str(),
        make_error<pdb::PDBError>(pdb::pdb_error_code::external_cmdline_ref));

  addObjFile(PrecompFile, &IndexMap);

  if (!PrecompFile->PCHSignature)
    fatal(PrecompFile->getName() + " is not a precompiled headers object");

  if (Precomp.getSignature() != PrecompFile->PCHSignature.getValueOr(0))
    return createFileError(
        Precomp.getPrecompFilePath().str(),
        make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));

  return IndexMap;
}

static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
  if (TI.isSimple())
    return true;
  if (TI.toArrayIndex() >= TypeIndexMap.size())
    return false;
  TI = TypeIndexMap[TI.toArrayIndex()];
  return true;
}

static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind,
                                     MutableArrayRef<uint8_t> RecordBytes,
                                     const CVIndexMap &IndexMap,
                                     ArrayRef<TiReference> TypeRefs) {
  MutableArrayRef<uint8_t> Contents =
      RecordBytes.drop_front(sizeof(RecordPrefix));
  for (const TiReference &Ref : TypeRefs) {
    unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
    if (Contents.size() < Ref.Offset + ByteSize)
      fatal("symbol record too short");

    // This can be an item index or a type index. Choose the appropriate map.
    ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap;
    bool IsItemIndex = Ref.Kind == TiRefKind::IndexRef;
    if (IsItemIndex && IndexMap.IsTypeServerMap)
      TypeOrItemMap = IndexMap.IPIMap;

    MutableArrayRef<TypeIndex> TIs(
        reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
    for (TypeIndex &TI : TIs) {
      if (!remapTypeIndex(TI, TypeOrItemMap)) {
        log("ignoring symbol record of kind 0x" + utohexstr(SymKind) + " in " +
            File->getName() + " with bad " + (IsItemIndex ? "item" : "type") +
            " index 0x" + utohexstr(TI.getIndex()));
        TI = TypeIndex(SimpleTypeKind::NotTranslated);
        continue;
      }
    }
  }
}

static void
recordStringTableReferenceAtOffset(MutableArrayRef<uint8_t> Contents,
                                   uint32_t Offset,
                                   std::vector<ulittle32_t *> &StrTableRefs) {
  Contents =
      Contents.drop_front(Offset).take_front(sizeof(support::ulittle32_t));
  ulittle32_t *Index = reinterpret_cast<ulittle32_t *>(Contents.data());
  StrTableRefs.push_back(Index);
}

static void
recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents,
                            std::vector<ulittle32_t *> &StrTableRefs) {
  // For now we only handle S_FILESTATIC, but we may need the same logic for
  // S_DEFRANGE and S_DEFRANGE_SUBFIELD.  However, I cannot seem to generate any
  // PDBs that contain these types of records, so because of the uncertainty
  // they are omitted here until we can prove that it's necessary.
  switch (Kind) {
  case SymbolKind::S_FILESTATIC:
    // FileStaticSym::ModFileOffset
    recordStringTableReferenceAtOffset(Contents, 8, StrTableRefs);
    break;
  case SymbolKind::S_DEFRANGE:
  case SymbolKind::S_DEFRANGE_SUBFIELD:
    log("Not fixing up string table reference in S_DEFRANGE / "
        "S_DEFRANGE_SUBFIELD record");
    break;
  default:
    break;
  }
}

static SymbolKind symbolKind(ArrayRef<uint8_t> RecordData) {
  const RecordPrefix *Prefix =
      reinterpret_cast<const RecordPrefix *>(RecordData.data());
  return static_cast<SymbolKind>(uint16_t(Prefix->RecordKind));
}

/// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32
static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData,
                               TypeCollection &IDTable) {
  RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(RecordData.data());

  SymbolKind Kind = symbolKind(RecordData);

  if (Kind == SymbolKind::S_PROC_ID_END) {
    Prefix->RecordKind = SymbolKind::S_END;
    return;
  }

  // In an object file, GPROC32_ID has an embedded reference which refers to the
  // single object file type index namespace.  This has already been translated
  // to the PDB file's ID stream index space, but we need to convert this to a
  // symbol that refers to the type stream index space.  So we remap again from
  // ID index space to type index space.
  if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) {
    SmallVector<TiReference, 1> Refs;
    auto Content = RecordData.drop_front(sizeof(RecordPrefix));
    CVSymbol Sym(RecordData);
    discoverTypeIndicesInSymbol(Sym, Refs);
    assert(Refs.size() == 1);
    assert(Refs.front().Count == 1);

    TypeIndex *TI =
        reinterpret_cast<TypeIndex *>(Content.data() + Refs[0].Offset);
    // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in
    // the IPI stream, whose `FunctionType` member refers to the TPI stream.
    // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and
    // in both cases we just need the second type index.
    if (!TI->isSimple() && !TI->isNoneType()) {
      CVType FuncIdData = IDTable.getType(*TI);
      SmallVector<TypeIndex, 2> Indices;
      discoverTypeIndices(FuncIdData, Indices);
      assert(Indices.size() == 2);
      *TI = Indices[1];
    }

    Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32
                                              : SymbolKind::S_LPROC32;
    Prefix->RecordKind = uint16_t(Kind);
  }
}

/// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned.
/// The object file may not be aligned.
static MutableArrayRef<uint8_t>
copyAndAlignSymbol(const CVSymbol &Sym, MutableArrayRef<uint8_t> &AlignedMem) {
  size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb));
  assert(Size >= 4 && "record too short");
  assert(Size <= MaxRecordLength && "record too long");
  assert(AlignedMem.size() >= Size && "didn't preallocate enough");

  // Copy the symbol record and zero out any padding bytes.
  MutableArrayRef<uint8_t> NewData = AlignedMem.take_front(Size);
  AlignedMem = AlignedMem.drop_front(Size);
  memcpy(NewData.data(), Sym.data().data(), Sym.length());
  memset(NewData.data() + Sym.length(), 0, Size - Sym.length());

  // Update the record prefix length. It should point to the beginning of the
  // next record.
  auto *Prefix = reinterpret_cast<RecordPrefix *>(NewData.data());
  Prefix->RecordLen = Size - 2;
  return NewData;
}

struct ScopeRecord {
  ulittle32_t PtrParent;
  ulittle32_t PtrEnd;
};

struct SymbolScope {
  ScopeRecord *OpeningRecord;
  uint32_t ScopeOffset;
};

static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack,
                           uint32_t CurOffset, CVSymbol &Sym) {
  assert(symbolOpensScope(Sym.kind()));
  SymbolScope S;
  S.ScopeOffset = CurOffset;
  S.OpeningRecord = const_cast<ScopeRecord *>(
      reinterpret_cast<const ScopeRecord *>(Sym.content().data()));
  S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset;
  Stack.push_back(S);
}

static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
                            uint32_t CurOffset, InputFile *File) {
  if (Stack.empty()) {
    warn("symbol scopes are not balanced in " + File->getName());
    return;
  }
  SymbolScope S = Stack.pop_back_val();
  S.OpeningRecord->PtrEnd = CurOffset;
}

static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {
  switch (Sym.kind()) {
  case SymbolKind::S_GDATA32:
  case SymbolKind::S_CONSTANT:
  // We really should not be seeing S_PROCREF and S_LPROCREF in the first place
  // since they are synthesized by the linker in response to S_GPROC32 and
  // S_LPROC32, but if we do see them, don't put them in the module stream I
  // guess.
  case SymbolKind::S_PROCREF:
  case SymbolKind::S_LPROCREF:
    return false;
  // S_UDT records go in the module stream if it is not a global S_UDT.
  case SymbolKind::S_UDT:
    return !IsGlobalScope;
  // S_GDATA32 does not go in the module stream, but S_LDATA32 does.
  case SymbolKind::S_LDATA32:
  default:
    return true;
  }
}

static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) {
  switch (Sym.kind()) {
  case SymbolKind::S_CONSTANT:
  case SymbolKind::S_GDATA32:
  // S_LDATA32 goes in both the module stream and the globals stream.
  case SymbolKind::S_LDATA32:
  case SymbolKind::S_GPROC32:
  case SymbolKind::S_LPROC32:
  // We really should not be seeing S_PROCREF and S_LPROCREF in the first place
  // since they are synthesized by the linker in response to S_GPROC32 and
  // S_LPROC32, but if we do see them, copy them straight through.
  case SymbolKind::S_PROCREF:
  case SymbolKind::S_LPROCREF:
    return true;
  // S_UDT records go in the globals stream if it is a global S_UDT.
  case SymbolKind::S_UDT:
    return IsGlobalScope;
  default:
    return false;
  }
}

static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex,
                            unsigned SymOffset, const CVSymbol &Sym) {
  switch (Sym.kind()) {
  case SymbolKind::S_CONSTANT:
  case SymbolKind::S_UDT:
  case SymbolKind::S_GDATA32:
  case SymbolKind::S_LDATA32:
  case SymbolKind::S_PROCREF:
  case SymbolKind::S_LPROCREF:
    Builder.addGlobalSymbol(Sym);
    break;
  case SymbolKind::S_GPROC32:
  case SymbolKind::S_LPROC32: {
    SymbolRecordKind K = SymbolRecordKind::ProcRefSym;
    if (Sym.kind() == SymbolKind::S_LPROC32)
      K = SymbolRecordKind::LocalProcRef;
    ProcRefSym PS(K);
    PS.Module = ModIndex;
    // For some reason, MSVC seems to add one to this value.
    ++PS.Module;
    PS.Name = getSymbolName(Sym);
    PS.SumName = 0;
    PS.SymOffset = SymOffset;
    Builder.addGlobalSymbol(PS);
    break;
  }
  default:
    llvm_unreachable("Invalid symbol kind!");
  }
}

void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap,
                                   std::vector<ulittle32_t *> &StringTableRefs,
                                   BinaryStreamRef SymData) {
  ArrayRef<uint8_t> SymsBuffer;
  cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer));
  SmallVector<SymbolScope, 4> Scopes;

  // Iterate every symbol to check if any need to be realigned, and if so, how
  // much space we need to allocate for them.
  bool NeedsRealignment = false;
  unsigned TotalRealignedSize = 0;
  auto EC = forEachCodeViewRecord<CVSymbol>(
      SymsBuffer, [&](CVSymbol Sym) -> llvm::Error {
        unsigned RealignedSize =
            alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb));
        NeedsRealignment |= RealignedSize != Sym.length();
        TotalRealignedSize += RealignedSize;
        return Error::success();
      });

  // If any of the symbol record lengths was corrupt, ignore them all, warn
  // about it, and move on.
  if (EC) {
    warn("corrupt symbol records in " + File->getName());
    consumeError(std::move(EC));
    return;
  }

  // If any symbol needed realignment, allocate enough contiguous memory for
  // them all. Typically symbol subsections are small enough that this will not
  // cause fragmentation.
  MutableArrayRef<uint8_t> AlignedSymbolMem;
  if (NeedsRealignment) {
    void *AlignedData =
        Alloc.Allocate(TotalRealignedSize, alignOf(CodeViewContainer::Pdb));
    AlignedSymbolMem = makeMutableArrayRef(
        reinterpret_cast<uint8_t *>(AlignedData), TotalRealignedSize);
  }

  // Iterate again, this time doing the real work.
  unsigned CurSymOffset = File->ModuleDBI->getNextSymbolOffset();
  ArrayRef<uint8_t> BulkSymbols;
  cantFail(forEachCodeViewRecord<CVSymbol>(
      SymsBuffer, [&](CVSymbol Sym) -> llvm::Error {
        // Align the record if required.
        MutableArrayRef<uint8_t> RecordBytes;
        if (NeedsRealignment) {
          RecordBytes = copyAndAlignSymbol(Sym, AlignedSymbolMem);
          Sym = CVSymbol(RecordBytes);
        } else {
          // Otherwise, we can actually mutate the symbol directly, since we
          // copied it to apply relocations.
          RecordBytes = makeMutableArrayRef(
              const_cast<uint8_t *>(Sym.data().data()), Sym.length());
        }

        // Discover type index references in the record. Skip it if we don't
        // know where they are.
        SmallVector<TiReference, 32> TypeRefs;
        if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) {
          log("ignoring unknown symbol record with kind 0x" +
              utohexstr(Sym.kind()));
          return Error::success();
        }

        // Re-map all the type index references.
        remapTypesInSymbolRecord(File, Sym.kind(), RecordBytes, IndexMap,
                                 TypeRefs);

        // An object file may have S_xxx_ID symbols, but these get converted to
        // "real" symbols in a PDB.
        translateIdSymbols(RecordBytes, TMerger.getIDTable());
        Sym = CVSymbol(RecordBytes);

        // If this record refers to an offset in the object file's string table,
        // add that item to the global PDB string table and re-write the index.
        recordStringTableReferences(Sym.kind(), RecordBytes, StringTableRefs);

        // Fill in "Parent" and "End" fields by maintaining a stack of scopes.
        if (symbolOpensScope(Sym.kind()))
          scopeStackOpen(Scopes, CurSymOffset, Sym);
        else if (symbolEndsScope(Sym.kind()))
          scopeStackClose(Scopes, CurSymOffset, File);

        // Add the symbol to the globals stream if necessary.  Do this before
        // adding the symbol to the module since we may need to get the next
        // symbol offset, and writing to the module's symbol stream will update
        // that offset.
        if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) {
          addGlobalSymbol(Builder.getGsiBuilder(),
                          File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym);
          ++GlobalSymbols;
        }

        if (symbolGoesInModuleStream(Sym, Scopes.empty())) {
          // Add symbols to the module in bulk. If this symbol is contiguous
          // with the previous run of symbols to add, combine the ranges. If
          // not, close the previous range of symbols and start a new one.
          if (Sym.data().data() == BulkSymbols.end()) {
            BulkSymbols = makeArrayRef(BulkSymbols.data(),
                                       BulkSymbols.size() + Sym.length());
          } else {
            File->ModuleDBI->addSymbolsInBulk(BulkSymbols);
            BulkSymbols = RecordBytes;
          }
          CurSymOffset += Sym.length();
          ++ModuleSymbols;
        }
        return Error::success();
      }));

  // Add any remaining symbols we've accumulated.
  File->ModuleDBI->addSymbolsInBulk(BulkSymbols);
}

// Allocate memory for a .debug$S / .debug$F section and relocate it.
static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
                                            SectionChunk &DebugChunk) {
  uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk.getSize());
  assert(DebugChunk.getOutputSectionIdx() == 0 &&
         "debug sections should not be in output sections");
  DebugChunk.writeTo(Buffer);
  return makeArrayRef(Buffer, DebugChunk.getSize());
}

static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {
  OutputSection *OS = C ? C->getOutputSection() : nullptr;
  pdb::SectionContrib SC;
  memset(&SC, 0, sizeof(SC));
  SC.ISect = OS ? OS->SectionIndex : llvm::pdb::kInvalidStreamIndex;
  SC.Off = C && OS ? C->getRVA() - OS->getRVA() : 0;
  SC.Size = C ? C->getSize() : -1;
  if (auto *SecChunk = dyn_cast_or_null<SectionChunk>(C)) {
    SC.Characteristics = SecChunk->Header->Characteristics;
    SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();
    ArrayRef<uint8_t> Contents = SecChunk->getContents();
    JamCRC CRC(0);
    ArrayRef<char> CharContents = makeArrayRef(
        reinterpret_cast<const char *>(Contents.data()), Contents.size());
    CRC.update(CharContents);
    SC.DataCrc = CRC.getCRC();
  } else {
    SC.Characteristics = OS ? OS->Header.Characteristics : 0;
    SC.Imod = Modi;
  }
  SC.RelocCrc = 0; // FIXME

  return SC;
}

static uint32_t
translateStringTableIndex(uint32_t ObjIndex,
                          const DebugStringTableSubsectionRef &ObjStrTable,
                          DebugStringTableSubsection &PdbStrTable) {
  auto ExpectedString = ObjStrTable.getString(ObjIndex);
  if (!ExpectedString) {
    warn("Invalid string table reference");
    consumeError(ExpectedString.takeError());
    return 0;
  }

  return PdbStrTable.insert(*ExpectedString);
}

void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) {
  DebugSubsectionArray Subsections;

  ArrayRef<uint8_t> RelocatedDebugContents = SectionChunk::consumeDebugMagic(
      relocateDebugChunk(Linker.Alloc, DebugS), DebugS.getSectionName());

  BinaryStreamReader Reader(RelocatedDebugContents, support::little);
  ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));

  for (const DebugSubsectionRecord &SS : Subsections) {
    switch (SS.kind()) {
    case DebugSubsectionKind::StringTable: {
      assert(!CVStrTab.valid() &&
             "Encountered multiple string table subsections!");
      ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
      break;
    }
    case DebugSubsectionKind::FileChecksums:
      assert(!Checksums.valid() &&
             "Encountered multiple checksum subsections!");
      ExitOnErr(Checksums.initialize(SS.getRecordData()));
      break;
    case DebugSubsectionKind::Lines:
      // We can add the relocated line table directly to the PDB without
      // modification because the file checksum offsets will stay the same.
      File.ModuleDBI->addDebugSubsection(SS);
      break;
    case DebugSubsectionKind::FrameData: {
      // We need to re-write string table indices here, so save off all
      // frame data subsections until we've processed the entire list of
      // subsections so that we can be sure we have the string table.
      DebugFrameDataSubsectionRef FDS;
      ExitOnErr(FDS.initialize(SS.getRecordData()));
      NewFpoFrames.push_back(std::move(FDS));
      break;
    }
    case DebugSubsectionKind::Symbols: {
      Linker.mergeSymbolRecords(&File, IndexMap, StringTableReferences,
                                SS.getRecordData());
      break;
    }
    default:
      // FIXME: Process the rest of the subsections.
      break;
    }
  }
}

void DebugSHandler::finish() {
  pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder();

  // We should have seen all debug subsections across the entire object file now
  // which means that if a StringTable subsection and Checksums subsection were
  // present, now is the time to handle them.
  if (!CVStrTab.valid()) {
    if (Checksums.valid())
      fatal(".debug$S sections with a checksums subsection must also contain a "
            "string table subsection");

    if (!StringTableReferences.empty())
      warn("No StringTable subsection was encountered, but there are string "
           "table references");
    return;
  }

  // Rewrite string table indices in the Fpo Data and symbol records to refer to
  // the global PDB string table instead of the object file string table.
  for (DebugFrameDataSubsectionRef &FDS : NewFpoFrames) {
    const ulittle32_t *Reloc = FDS.getRelocPtr();
    for (codeview::FrameData FD : FDS) {
      FD.RvaStart += *Reloc;
      FD.FrameFunc =
          translateStringTableIndex(FD.FrameFunc, CVStrTab, Linker.PDBStrTab);
      DbiBuilder.addNewFpoData(FD);
    }
  }

  for (ulittle32_t *Ref : StringTableReferences)
    *Ref = translateStringTableIndex(*Ref, CVStrTab, Linker.PDBStrTab);

  // Make a new file checksum table that refers to offsets in the PDB-wide
  // string table. Generally the string table subsection appears after the
  // checksum table, so we have to do this after looping over all the
  // subsections.
  auto NewChecksums = make_unique<DebugChecksumsSubsection>(Linker.PDBStrTab);
  for (FileChecksumEntry &FC : Checksums) {
    SmallString<128> FileName =
        ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
    pdbMakeAbsolute(FileName);
    ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile(
        *File.ModuleDBI, FileName));
    NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
  }
  File.ModuleDBI->addDebugSubsection(std::move(NewChecksums));
}

void PDBLinker::addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap) {
  if (File->MergedIntoPDB)
    return;
  File->MergedIntoPDB = true;

  // Before we can process symbol substreams from .debug$S, we need to process
  // type information, file checksums, and the string table.  Add type info to
  // the PDB first, so that we can get the map from object file type and item
  // indices to PDB type and item indices.
  CVIndexMap ObjectIndexMap;
  auto IndexMapResult =
      mergeDebugT(File, ExternIndexMap ? ExternIndexMap : &ObjectIndexMap);

  // If the .debug$T sections fail to merge, assume there is no debug info.
  if (!IndexMapResult) {
    if (!Config->WarnDebugInfoUnusable) {
      consumeError(IndexMapResult.takeError());
      return;
    }
    warn("Cannot use debug info for '" + toString(File) + "' [LNK4099]\n" +
         ">>> failed to load reference " +
         StringRef(toString(IndexMapResult.takeError())));
    return;
  }

  ScopedTimer T(SymbolMergingTimer);

  pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
  DebugSHandler DSH(*this, *File, *IndexMapResult);
  // Now do all live .debug$S and .debug$F sections.
  for (SectionChunk *DebugChunk : File->getDebugChunks()) {
    if (!DebugChunk->Live || DebugChunk->getSize() == 0)
      continue;

    if (DebugChunk->getSectionName() == ".debug$S") {
      DSH.handleDebugS(*DebugChunk);
      continue;
    }

    if (DebugChunk->getSectionName() == ".debug$F") {
      ArrayRef<uint8_t> RelocatedDebugContents =
          relocateDebugChunk(Alloc, *DebugChunk);

      FixedStreamArray<object::FpoData> FpoRecords;
      BinaryStreamReader Reader(RelocatedDebugContents, support::little);
      uint32_t Count = RelocatedDebugContents.size() / sizeof(object::FpoData);
      ExitOnErr(Reader.readArray(FpoRecords, Count));

      // These are already relocated and don't refer to the string table, so we
      // can just copy it.
      for (const object::FpoData &FD : FpoRecords)
        DbiBuilder.addOldFpoData(FD);
      continue;
    }
  }

  // Do any post-processing now that all .debug$S sections have been processed.
  DSH.finish();
}

// Add a module descriptor for every object file. We need to put an absolute
// path to the object into the PDB. If this is a plain object, we make its
// path absolute. If it's an object in an archive, we make the archive path
// absolute.
static void createModuleDBI(pdb::PDBFileBuilder &Builder) {
  pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
  SmallString<128> ObjName;

  for (ObjFile *File : ObjFile::Instances) {

    bool InArchive = !File->ParentName.empty();
    ObjName = InArchive ? File->ParentName : File->getName();
    pdbMakeAbsolute(ObjName);
    StringRef ModName = InArchive ? File->getName() : StringRef(ObjName);

    File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(ModName));
    File->ModuleDBI->setObjFileName(ObjName);

    ArrayRef<Chunk *> Chunks = File->getChunks();
    uint32_t Modi = File->ModuleDBI->getModuleIndex();

    for (Chunk *C : Chunks) {
      auto *SecChunk = dyn_cast<SectionChunk>(C);
      if (!SecChunk || !SecChunk->Live)
        continue;
      pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi);
      File->ModuleDBI->setFirstSectionContrib(SC);
      break;
    }
  }
}

static PublicSym32 createPublic(Defined *Def) {
  PublicSym32 Pub(SymbolKind::S_PUB32);
  Pub.Name = Def->getName();
  if (auto *D = dyn_cast<DefinedCOFF>(Def)) {
    if (D->getCOFFSymbol().isFunctionDefinition())
      Pub.Flags = PublicSymFlags::Function;
  } else if (isa<DefinedImportThunk>(Def)) {
    Pub.Flags = PublicSymFlags::Function;
  }

  OutputSection *OS = Def->getChunk()->getOutputSection();
  assert(OS && "all publics should be in final image");
  Pub.Offset = Def->getRVA() - OS->getRVA();
  Pub.Segment = OS->SectionIndex;
  return Pub;
}

// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
void PDBLinker::addObjectsToPDB() {
  ScopedTimer T1(AddObjectsTimer);

  createModuleDBI(Builder);

  for (ObjFile *File : ObjFile::Instances)
    addObjFile(File);

  Builder.getStringTableBuilder().setStrings(PDBStrTab);
  T1.stop();

  // Construct TPI and IPI stream contents.
  ScopedTimer T2(TpiStreamLayoutTimer);
  addTypeInfo(Builder.getTpiBuilder(), TMerger.getTypeTable());
  addTypeInfo(Builder.getIpiBuilder(), TMerger.getIDTable());
  T2.stop();

  ScopedTimer T3(GlobalsLayoutTimer);
  // Compute the public and global symbols.
  auto &GsiBuilder = Builder.getGsiBuilder();
  std::vector<PublicSym32> Publics;
  Symtab->forEachSymbol([&Publics](Symbol *S) {
    // Only emit defined, live symbols that have a chunk.
    auto *Def = dyn_cast<Defined>(S);
    if (Def && Def->isLive() && Def->getChunk())
      Publics.push_back(createPublic(Def));
  });

  if (!Publics.empty()) {
    PublicSymbols = Publics.size();
    // Sort the public symbols and add them to the stream.
    parallelSort(Publics, [](const PublicSym32 &L, const PublicSym32 &R) {
      return L.Name < R.Name;
    });
    for (const PublicSym32 &Pub : Publics)
      GsiBuilder.addPublicSymbol(Pub);
  }
}

void PDBLinker::printStats() {
  if (!Config->ShowSummary)
    return;

  SmallString<256> Buffer;
  raw_svector_ostream Stream(Buffer);

  Stream << center_justify("Summary", 80) << '\n'
         << std::string(80, '-') << '\n';

  auto Print = [&](uint64_t V, StringRef S) {
    Stream << format_decimal(V, 15) << " " << S << '\n';
  };

  Print(ObjFile::Instances.size(),
        "Input OBJ files (expanded from all cmd-line inputs)");
  Print(TypeServerIndexMappings.size(), "PDB type server dependencies");
  Print(PrecompTypeIndexMappings.size(), "Precomp OBJ dependencies");
  Print(TMerger.getTypeTable().size() + TMerger.getIDTable().size(),
        "Merged TPI records");
  Print(PDBStrTab.size(), "Output PDB strings");
  Print(GlobalSymbols, "Global symbol records");
  Print(ModuleSymbols, "Module symbol records");
  Print(PublicSymbols, "Public symbol records");

  message(Buffer);
}

void PDBLinker::addNatvisFiles() {
  for (StringRef File : Config->NatvisFiles) {
    ErrorOr<std::unique_ptr<MemoryBuffer>> DataOrErr =
        MemoryBuffer::getFile(File);
    if (!DataOrErr) {
      warn("Cannot open input file: " + File);
      continue;
    }
    Builder.addInjectedSource(File, std::move(*DataOrErr));
  }
}

static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) {
  switch (Machine) {
  case COFF::IMAGE_FILE_MACHINE_AMD64:
    return codeview::CPUType::X64;
  case COFF::IMAGE_FILE_MACHINE_ARM:
    return codeview::CPUType::ARM7;
  case COFF::IMAGE_FILE_MACHINE_ARM64:
    return codeview::CPUType::ARM64;
  case COFF::IMAGE_FILE_MACHINE_ARMNT:
    return codeview::CPUType::ARMNT;
  case COFF::IMAGE_FILE_MACHINE_I386:
    return codeview::CPUType::Intel80386;
  default:
    llvm_unreachable("Unsupported CPU Type");
  }
}

// Mimic MSVC which surrounds arguments containing whitespace with quotes.
// Double double-quotes are handled, so that the resulting string can be
// executed again on the cmd-line.
static std::string quote(ArrayRef<StringRef> Args) {
  std::string R;
  R.reserve(256);
  for (StringRef A : Args) {
    if (!R.empty())
      R.push_back(' ');
    bool HasWS = A.find(' ') != StringRef::npos;
    bool HasQ = A.find('"') != StringRef::npos;
    if (HasWS || HasQ)
      R.push_back('"');
    if (HasQ) {
      SmallVector<StringRef, 4> S;
      A.split(S, '"');
      R.append(join(S, "\"\""));
    } else {
      R.append(A);
    }
    if (HasWS || HasQ)
      R.push_back('"');
  }
  return R;
}

static void fillLinkerVerRecord(Compile3Sym &CS) {
  CS.Machine = toCodeViewMachine(Config->Machine);
  // Interestingly, if we set the string to 0.0.0.0, then when trying to view
  // local variables WinDbg emits an error that private symbols are not present.
  // By setting this to a valid MSVC linker version string, local variables are
  // displayed properly.   As such, even though it is not representative of
  // LLVM's version information, we need this for compatibility.
  CS.Flags = CompileSym3Flags::None;
  CS.VersionBackendBuild = 25019;
  CS.VersionBackendMajor = 14;
  CS.VersionBackendMinor = 10;
  CS.VersionBackendQFE = 0;

  // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the
  // linker module (which is by definition a backend), so we don't need to do
  // anything here.  Also, it seems we can use "LLVM Linker" for the linker name
  // without any problems.  Only the backend version has to be hardcoded to a
  // magic number.
  CS.VersionFrontendBuild = 0;
  CS.VersionFrontendMajor = 0;
  CS.VersionFrontendMinor = 0;
  CS.VersionFrontendQFE = 0;
  CS.Version = "LLVM Linker";
  CS.setLanguage(SourceLanguage::Link);
}

static void addCommonLinkerModuleSymbols(StringRef Path,
                                         pdb::DbiModuleDescriptorBuilder &Mod,
                                         BumpPtrAllocator &Allocator) {
  ObjNameSym ONS(SymbolRecordKind::ObjNameSym);
  EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym);
  Compile3Sym CS(SymbolRecordKind::Compile3Sym);
  fillLinkerVerRecord(CS);

  ONS.Name = "* Linker *";
  ONS.Signature = 0;

  ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front();
  std::string ArgStr = quote(Args);
  EBS.Fields.push_back("cwd");
  SmallString<64> cwd;
  if (Config->PDBSourcePath.empty())
    sys::fs::current_path(cwd);
  else
    cwd = Config->PDBSourcePath;
  EBS.Fields.push_back(cwd);
  EBS.Fields.push_back("exe");
  SmallString<64> exe = Config->Argv[0];
  pdbMakeAbsolute(exe);
  EBS.Fields.push_back(exe);
  EBS.Fields.push_back("pdb");
  EBS.Fields.push_back(Path);
  EBS.Fields.push_back("cmd");
  EBS.Fields.push_back(ArgStr);
  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
      ONS, Allocator, CodeViewContainer::Pdb));
  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
      CS, Allocator, CodeViewContainer::Pdb));
  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
      EBS, Allocator, CodeViewContainer::Pdb));
}

static void addLinkerModuleCoffGroup(PartialSection *Sec,
                                     pdb::DbiModuleDescriptorBuilder &Mod,
                                     OutputSection &OS,
                                     BumpPtrAllocator &Allocator) {
  // If there's a section, there's at least one chunk
  assert(!Sec->Chunks.empty());
  const Chunk *firstChunk = *Sec->Chunks.begin();
  const Chunk *lastChunk = *Sec->Chunks.rbegin();

  // Emit COFF group
  CoffGroupSym CGS(SymbolRecordKind::CoffGroupSym);
  CGS.Name = Sec->Name;
  CGS.Segment = OS.SectionIndex;
  CGS.Offset = firstChunk->getRVA() - OS.getRVA();
  CGS.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA();
  CGS.Characteristics = Sec->Characteristics;

  // Somehow .idata sections & sections groups in the debug symbol stream have
  // the "write" flag set. However the section header for the corresponding
  // .idata section doesn't have it.
  if (CGS.Name.startswith(".idata"))
    CGS.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE;

  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
      CGS, Allocator, CodeViewContainer::Pdb));
}

static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod,
                                         OutputSection &OS,
                                         BumpPtrAllocator &Allocator) {
  SectionSym Sym(SymbolRecordKind::SectionSym);
  Sym.Alignment = 12; // 2^12 = 4KB
  Sym.Characteristics = OS.Header.Characteristics;
  Sym.Length = OS.getVirtualSize();
  Sym.Name = OS.Name;
  Sym.Rva = OS.getRVA();
  Sym.SectionNumber = OS.SectionIndex;
  Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
      Sym, Allocator, CodeViewContainer::Pdb));

  // Skip COFF groups in MinGW because it adds a significant footprint to the
  // PDB, due to each function being in its own section
  if (Config->MinGW)
    return;

  // Output COFF groups for individual chunks of this section.
  for (PartialSection *Sec : OS.ContribSections) {
    addLinkerModuleCoffGroup(Sec, Mod, OS, Allocator);
  }
}

// Add all import files as modules to the PDB.
void PDBLinker::addImportFilesToPDB(ArrayRef<OutputSection *> OutputSections) {
  if (ImportFile::Instances.empty())
    return;

  std::map<std::string, llvm::pdb::DbiModuleDescriptorBuilder *> DllToModuleDbi;

  for (ImportFile *File : ImportFile::Instances) {
    if (!File->Live)
      continue;

    if (!File->ThunkSym)
      continue;

    if (!File->ThunkLive)
        continue;

    std::string DLL = StringRef(File->DLLName).lower();
    llvm::pdb::DbiModuleDescriptorBuilder *&Mod = DllToModuleDbi[DLL];
    if (!Mod) {
      pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
      SmallString<128> LibPath = File->ParentName;
      pdbMakeAbsolute(LibPath);
      sys::path::native(LibPath);

      // Name modules similar to MSVC's link.exe.
      // The first module is the simple dll filename
      llvm::pdb::DbiModuleDescriptorBuilder &FirstMod =
          ExitOnErr(DbiBuilder.addModuleInfo(File->DLLName));
      FirstMod.setObjFileName(LibPath);
      pdb::SectionContrib SC =
          createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex);
      FirstMod.setFirstSectionContrib(SC);

      // The second module is where the import stream goes.
      Mod = &ExitOnErr(DbiBuilder.addModuleInfo("Import:" + File->DLLName));
      Mod->setObjFileName(LibPath);
    }

    DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym);
    Chunk *ThunkChunk = Thunk->getChunk();
    OutputSection *ThunkOS = ThunkChunk->getOutputSection();

    ObjNameSym ONS(SymbolRecordKind::ObjNameSym);
    Compile3Sym CS(SymbolRecordKind::Compile3Sym);
    Thunk32Sym TS(SymbolRecordKind::Thunk32Sym);
    ScopeEndSym ES(SymbolRecordKind::ScopeEndSym);

    ONS.Name = File->DLLName;
    ONS.Signature = 0;

    fillLinkerVerRecord(CS);

    TS.Name = Thunk->getName();
    TS.Parent = 0;
    TS.End = 0;
    TS.Next = 0;
    TS.Thunk = ThunkOrdinal::Standard;
    TS.Length = ThunkChunk->getSize();
    TS.Segment = ThunkOS->SectionIndex;
    TS.Offset = ThunkChunk->getRVA() - ThunkOS->getRVA();

    Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
        ONS, Alloc, CodeViewContainer::Pdb));
    Mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
        CS, Alloc, CodeViewContainer::Pdb));

    SmallVector<SymbolScope, 4> Scopes;
    CVSymbol NewSym = codeview::SymbolSerializer::writeOneSymbol(
        TS, Alloc, CodeViewContainer::Pdb);
    scopeStackOpen(Scopes, Mod->getNextSymbolOffset(), NewSym);

    Mod->addSymbol(NewSym);

    NewSym = codeview::SymbolSerializer::writeOneSymbol(ES, Alloc,
                                                        CodeViewContainer::Pdb);
    scopeStackClose(Scopes, Mod->getNextSymbolOffset(), File);

    Mod->addSymbol(NewSym);

    pdb::SectionContrib SC =
        createSectionContrib(Thunk->getChunk(), Mod->getModuleIndex());
    Mod->setFirstSectionContrib(SC);
  }
}

// Creates a PDB file.
void coff::createPDB(SymbolTable *Symtab,
                     ArrayRef<OutputSection *> OutputSections,
                     ArrayRef<uint8_t> SectionTable,
                     llvm::codeview::DebugInfo *BuildId) {
  ScopedTimer T1(TotalPdbLinkTimer);
  PDBLinker PDB(Symtab);

  PDB.initialize(BuildId);
  PDB.addObjectsToPDB();
  PDB.addImportFilesToPDB(OutputSections);
  PDB.addSections(OutputSections, SectionTable);
  PDB.addNatvisFiles();

  ScopedTimer T2(DiskCommitTimer);
  codeview::GUID Guid;
  PDB.commit(&Guid);
  memcpy(&BuildId->PDB70.Signature, &Guid, 16);

  T2.stop();
  T1.stop();
  PDB.printStats();
}

void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) {
  ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize

  BuildId->Signature.CVSignature = OMF::Signature::PDB70;
  // Signature is set to a hash of the PDB contents when the PDB is done.
  memset(BuildId->PDB70.Signature, 0, 16);
  BuildId->PDB70.Age = 1;

  // Create streams in MSF for predefined streams, namely
  // PDB, TPI, DBI and IPI.
  for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)
    ExitOnErr(Builder.getMsfBuilder().addStream(0));

  // Add an Info stream.
  auto &InfoBuilder = Builder.getInfoBuilder();
  InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
  InfoBuilder.setHashPDBContentsToGUID(true);

  // Add an empty DBI stream.
  pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
  DbiBuilder.setAge(BuildId->PDB70.Age);
  DbiBuilder.setVersionHeader(pdb::PdbDbiV70);
  DbiBuilder.setMachineType(Config->Machine);
  // Technically we are not link.exe 14.11, but there are known cases where
  // debugging tools on Windows expect Microsoft-specific version numbers or
  // they fail to work at all.  Since we know we produce PDBs that are
  // compatible with LINK 14.11, we set that version number here.
  DbiBuilder.setBuildNumber(14, 11);
}

void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,
                            ArrayRef<uint8_t> SectionTable) {
  // It's not entirely clear what this is, but the * Linker * module uses it.
  pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
  NativePath = Config->PDBPath;
  pdbMakeAbsolute(NativePath);
  uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);
  auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));
  LinkerModule.setPdbFilePathNI(PdbFilePathNI);
  addCommonLinkerModuleSymbols(NativePath, LinkerModule, Alloc);

  // Add section contributions. They must be ordered by ascending RVA.
  for (OutputSection *OS : OutputSections) {
    addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc);
    for (Chunk *C : OS->Chunks) {
      pdb::SectionContrib SC =
          createSectionContrib(C, LinkerModule.getModuleIndex());
      Builder.getDbiBuilder().addSectionContrib(SC);
    }
  }

  // The * Linker * first section contrib is only used along with /INCREMENTAL,
  // to provide trampolines thunks for incremental function patching. Set this
  // as "unused" because LLD doesn't support /INCREMENTAL link.
  pdb::SectionContrib SC =
      createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex);
  LinkerModule.setFirstSectionContrib(SC);

  // Add Section Map stream.
  ArrayRef<object::coff_section> Sections = {
      (const object::coff_section *)SectionTable.data(),
      SectionTable.size() / sizeof(object::coff_section)};
  SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);
  DbiBuilder.setSectionMap(SectionMap);

  // Add COFF section header stream.
  ExitOnErr(
      DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));
}

void PDBLinker::commit(codeview::GUID *Guid) {
  // Write to a file.
  ExitOnErr(Builder.commit(Config->PDBPath, Guid));
}

static Expected<StringRef>
getFileName(const DebugStringTableSubsectionRef &Strings,
            const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
  auto Iter = Checksums.getArray().at(FileID);
  if (Iter == Checksums.getArray().end())
    return make_error<CodeViewError>(cv_error_code::no_records);
  uint32_t Offset = Iter->FileNameOffset;
  return Strings.getString(Offset);
}

static uint32_t getSecrelReloc() {
  switch (Config->Machine) {
  case AMD64:
    return COFF::IMAGE_REL_AMD64_SECREL;
  case I386:
    return COFF::IMAGE_REL_I386_SECREL;
  case ARMNT:
    return COFF::IMAGE_REL_ARM_SECREL;
  case ARM64:
    return COFF::IMAGE_REL_ARM64_SECREL;
  default:
    llvm_unreachable("unknown machine type");
  }
}

// Try to find a line table for the given offset Addr into the given chunk C.
// If a line table was found, the line table, the string and checksum tables
// that are used to interpret the line table, and the offset of Addr in the line
// table are stored in the output arguments. Returns whether a line table was
// found.
static bool findLineTable(const SectionChunk *C, uint32_t Addr,
                          DebugStringTableSubsectionRef &CVStrTab,
                          DebugChecksumsSubsectionRef &Checksums,
                          DebugLinesSubsectionRef &Lines,
                          uint32_t &OffsetInLinetable) {
  ExitOnError ExitOnErr;
  uint32_t SecrelReloc = getSecrelReloc();

  for (SectionChunk *DbgC : C->File->getDebugChunks()) {
    if (DbgC->getSectionName() != ".debug$S")
      continue;

    // Build a mapping of SECREL relocations in DbgC that refer to C.
    DenseMap<uint32_t, uint32_t> Secrels;
    for (const coff_relocation &R : DbgC->getRelocs()) {
      if (R.Type != SecrelReloc)
        continue;

      if (auto *S = dyn_cast_or_null<DefinedRegular>(
              C->File->getSymbols()[R.SymbolTableIndex]))
        if (S->getChunk() == C)
          Secrels[R.VirtualAddress] = S->getValue();
    }

    ArrayRef<uint8_t> Contents =
        SectionChunk::consumeDebugMagic(DbgC->getContents(), ".debug$S");
    DebugSubsectionArray Subsections;
    BinaryStreamReader Reader(Contents, support::little);
    ExitOnErr(Reader.readArray(Subsections, Contents.size()));

    for (const DebugSubsectionRecord &SS : Subsections) {
      switch (SS.kind()) {
      case DebugSubsectionKind::StringTable: {
        assert(!CVStrTab.valid() &&
               "Encountered multiple string table subsections!");
        ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
        break;
      }
      case DebugSubsectionKind::FileChecksums:
        assert(!Checksums.valid() &&
               "Encountered multiple checksum subsections!");
        ExitOnErr(Checksums.initialize(SS.getRecordData()));
        break;
      case DebugSubsectionKind::Lines: {
        ArrayRef<uint8_t> Bytes;
        auto Ref = SS.getRecordData();
        ExitOnErr(Ref.readLongestContiguousChunk(0, Bytes));
        size_t OffsetInDbgC = Bytes.data() - DbgC->getContents().data();

        // Check whether this line table refers to C.
        auto I = Secrels.find(OffsetInDbgC);
        if (I == Secrels.end())
          break;

        // Check whether this line table covers Addr in C.
        DebugLinesSubsectionRef LinesTmp;
        ExitOnErr(LinesTmp.initialize(BinaryStreamReader(Ref)));
        uint32_t OffsetInC = I->second + LinesTmp.header()->RelocOffset;
        if (Addr < OffsetInC || Addr >= OffsetInC + LinesTmp.header()->CodeSize)
          break;

        assert(!Lines.header() &&
               "Encountered multiple line tables for function!");
        ExitOnErr(Lines.initialize(BinaryStreamReader(Ref)));
        OffsetInLinetable = Addr - OffsetInC;
        break;
      }
      default:
        break;
      }

      if (CVStrTab.valid() && Checksums.valid() && Lines.header())
        return true;
    }
  }

  return false;
}

// Use CodeView line tables to resolve a file and line number for the given
// offset into the given chunk and return them, or {"", 0} if a line table was
// not found.
std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *C,
                                                 uint32_t Addr) {
  ExitOnError ExitOnErr;

  DebugStringTableSubsectionRef CVStrTab;
  DebugChecksumsSubsectionRef Checksums;
  DebugLinesSubsectionRef Lines;
  uint32_t OffsetInLinetable;

  if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable))
    return {"", 0};

  Optional<uint32_t> NameIndex;
  Optional<uint32_t> LineNumber;
  for (LineColumnEntry &Entry : Lines) {
    for (const LineNumberEntry &LN : Entry.LineNumbers) {
      LineInfo LI(LN.Flags);
      if (LN.Offset > OffsetInLinetable) {
        if (!NameIndex) {
          NameIndex = Entry.NameIndex;
          LineNumber = LI.getStartLine();
        }
        StringRef Filename =
            ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex));
        return {Filename, *LineNumber};
      }
      NameIndex = Entry.NameIndex;
      LineNumber = LI.getStartLine();
    }
  }
  if (!NameIndex)
    return {"", 0};
  StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex));
  return {Filename, *LineNumber};
}
