Example #1
0
File: PDB.cpp Project: Leedehai/lld
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
// TpiData.
static void addObjectsToPDB(BumpPtrAllocator &Alloc, SymbolTable *Symtab,
                            pdb::PDBFileBuilder &Builder,
                            TypeTableBuilder &TypeTable,
                            TypeTableBuilder &IDTable) {
  // Follow type servers.  If the same type server is encountered more than
  // once for this instance of `PDBTypeServerHandler` (for example if many
  // object files reference the same TypeServer), the types from the
  // TypeServer will only be visited once.
  pdb::PDBTypeServerHandler Handler;

  // PDBs use a single global string table for filenames in the file checksum
  // table.
  auto PDBStrTab = std::make_shared<DebugStringTableSubsection>();

  // Visit all .debug$T sections to add them to Builder.
  for (ObjectFile *File : Symtab->ObjectFiles) {
    // 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.
    bool InArchive = !File->ParentName.empty();
    SmallString<128> Path = InArchive ? File->ParentName : File->getName();
    sys::fs::make_absolute(Path);
    StringRef Name = InArchive ? File->getName() : StringRef(Path);
    File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
    File->ModuleDBI->setObjFileName(Path);

    // 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.
    SmallVector<TypeIndex, 128> TypeIndexMap;
    mergeDebugT(File, IDTable, TypeTable, TypeIndexMap, Handler);

    // Now do all line info.
    for (SectionChunk *DebugChunk : File->getDebugChunks()) {
      if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S")
        continue;

      ArrayRef<uint8_t> RelocatedDebugContents =
          relocateDebugChunk(Alloc, DebugChunk);
      if (RelocatedDebugContents.empty())
        continue;

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

      DebugStringTableSubsectionRef CVStrTab;
      DebugChecksumsSubsectionRef Checksums;
      for (const DebugSubsectionRecord &SS : Subsections) {
        switch (SS.kind()) {
        case DebugSubsectionKind::StringTable:
          ExitOnErr(CVStrTab.initialize(SS.getRecordData()));
          break;
        case DebugSubsectionKind::FileChecksums:
          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::Symbols:
          mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData());
          break;
        default:
          // FIXME: Process the rest of the subsections.
          break;
        }
      }

      if (Checksums.valid()) {
        // 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.
        if (!CVStrTab.valid())
          fatal(".debug$S sections must have both a string table subsection "
                "and a checksum subsection table or neither");
        auto NewChecksums =
            make_unique<DebugChecksumsSubsection>(*PDBStrTab);
        for (FileChecksumEntry &FC : Checksums) {
          StringRef FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset));
          ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(
              *File->ModuleDBI, FileName));
          NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
        }
        File->ModuleDBI->addDebugSubsection(std::move(NewChecksums));
      }
    }
  }

  Builder.getStringTableBuilder().setStrings(*PDBStrTab);

  // Construct TPI stream contents.
  addTypeInfo(Builder.getTpiBuilder(), TypeTable);

  // Construct IPI stream contents.
  addTypeInfo(Builder.getIpiBuilder(), IDTable);
}