Example #1
0
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                           DefRangeSym &DefRange) {
  if (ObjDelegate) {
    DebugStringTableSubsectionRef Strings = ObjDelegate->getStringTable();
    auto ExpectedProgram = Strings.getString(DefRange.Program);
    if (!ExpectedProgram) {
      consumeError(ExpectedProgram.takeError());
      return llvm::make_error<CodeViewError>(
          "String table offset outside of bounds of String Table!");
    }
    W.printString("Program", *ExpectedProgram);
  }
  printLocalVariableAddrRange(DefRange.Range, DefRange.getRelocationOffset());
  printLocalVariableAddrGap(DefRange.Gaps);
  return Error::success();
}
Expected<std::shared_ptr<YAMLFrameDataSubsection>>
YAMLFrameDataSubsection::fromCodeViewSubsection(
    const DebugStringTableSubsectionRef &Strings,
    const DebugFrameDataSubsectionRef &Frames) {
  auto Result = std::make_shared<YAMLFrameDataSubsection>();
  for (const auto &F : Frames) {
    YAMLFrameData YF;
    YF.CodeSize = F.CodeSize;
    YF.Flags = F.Flags;
    YF.LocalSize = F.LocalSize;
    YF.MaxStackSize = F.MaxStackSize;
    YF.ParamsSize = F.ParamsSize;
    YF.PrologSize = F.PrologSize;
    YF.RvaStart = F.RvaStart;
    YF.SavedRegsSize = F.SavedRegsSize;

    auto ES = Strings.getString(F.FrameFunc);
    if (!ES)
      return joinErrors(
          make_error<CodeViewError>(
              cv_error_code::no_records,
              "Could not find string for string id while mapping FrameData!"),
          ES.takeError());
    YF.FrameFunc = *ES;
    Result->Frames.push_back(YF);
  }
  return Result;
}
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 Expected<SourceFileChecksumEntry>
convertOneChecksum(const DebugStringTableSubsectionRef &Strings,
                   const FileChecksumEntry &CS) {
  auto ExpectedString = Strings.getString(CS.FileNameOffset);
  if (!ExpectedString)
    return ExpectedString.takeError();

  SourceFileChecksumEntry Result;
  Result.ChecksumBytes.Bytes = CS.Checksum;
  Result.Kind = CS.Kind;
  Result.FileName = *ExpectedString;
  return Result;
}
Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
    const DebugStringTableSubsectionRef &Strings,
    const DebugCrossModuleImportsSubsectionRef &Imports) {
  auto Result = std::make_shared<YAMLCrossModuleImportsSubsection>();
  for (const auto &CMI : Imports) {
    YAMLCrossModuleImport YCMI;
    auto ExpectedStr = Strings.getString(CMI.Header->ModuleNameOffset);
    if (!ExpectedStr)
      return ExpectedStr.takeError();
    YCMI.ModuleName = *ExpectedStr;
    YCMI.ImportIds.assign(CMI.Imports.begin(), CMI.Imports.end());
    Result->Imports.push_back(YCMI);
  }
  return Result;
}
Expected<std::shared_ptr<YAMLStringTableSubsection>>
YAMLStringTableSubsection::fromCodeViewSubsection(
    const DebugStringTableSubsectionRef &Strings) {
  auto Result = std::make_shared<YAMLStringTableSubsection>();
  BinaryStreamReader Reader(Strings.getBuffer());
  StringRef S;
  // First item is a single null string, skip it.
  if (auto EC = Reader.readCString(S))
    return std::move(EC);
  assert(S.empty());
  while (Reader.bytesRemaining() > 0) {
    if (auto EC = Reader.readCString(S))
      return std::move(EC);
    Result->Strings.push_back(S);
  }
  return Result;
}
Example #7
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);
}
Error llvm::codeview::visitDebugSubsection(
    const DebugSubsectionRecord &R, DebugSubsectionVisitor &V,
    const StringsAndChecksumsRef &State) {
  BinaryStreamReader Reader(R.getRecordData());
  switch (R.kind()) {
  case DebugSubsectionKind::Lines: {
    DebugLinesSubsectionRef Fragment;
    if (auto EC = Fragment.initialize(Reader))
      return EC;

    return V.visitLines(Fragment, State);
  }
  case DebugSubsectionKind::FileChecksums: {
    DebugChecksumsSubsectionRef Fragment;
    if (auto EC = Fragment.initialize(Reader))
      return EC;

    return V.visitFileChecksums(Fragment, State);
  }
  case DebugSubsectionKind::InlineeLines: {
    DebugInlineeLinesSubsectionRef Fragment;
    if (auto EC = Fragment.initialize(Reader))
      return EC;
    return V.visitInlineeLines(Fragment, State);
  }
  case DebugSubsectionKind::CrossScopeExports: {
    DebugCrossModuleExportsSubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitCrossModuleExports(Section, State);
  }
  case DebugSubsectionKind::CrossScopeImports: {
    DebugCrossModuleImportsSubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitCrossModuleImports(Section, State);
  }
  case DebugSubsectionKind::Symbols: {
    DebugSymbolsSubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitSymbols(Section, State);
  }
  case DebugSubsectionKind::StringTable: {
    DebugStringTableSubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitStringTable(Section, State);
  }
  case DebugSubsectionKind::FrameData: {
    DebugFrameDataSubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitFrameData(Section, State);
  }
  case DebugSubsectionKind::CoffSymbolRVA: {
    DebugSymbolRVASubsectionRef Section;
    if (auto EC = Section.initialize(Reader))
      return EC;
    return V.visitCOFFSymbolRVAs(Section, State);
  }
  default: {
    DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
    return V.visitUnknown(Fragment);
  }
  }
}