Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const {
  // Write a hash table.
  uint32_t BucketCount = computeBucketCount(Strings.size());
  if (auto EC = Writer.writeInteger(BucketCount))
    return EC;
  std::vector<ulittle32_t> Buckets(BucketCount);

  for (auto &Pair : Strings) {
    StringRef S = Pair.getKey();
    uint32_t Offset = Pair.getValue();
    uint32_t Hash = hashStringV1(S);

    for (uint32_t I = 0; I != BucketCount; ++I) {
      uint32_t Slot = (Hash + I) % BucketCount;
      if (Buckets[Slot] != 0)
        continue;
      Buckets[Slot] = Offset;
      break;
    }
  }

  if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
    return EC;

  assert(Writer.bytesRemaining() == 0);
  return Error::success();
}
Example #2
0
Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer,
                                      SparseBitVector<> &Vec) {
  constexpr int BitsPerWord = 8 * sizeof(uint32_t);

  int ReqBits = Vec.find_last() + 1;
  uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord;
  if (auto EC = Writer.writeInteger(ReqWords))
    return joinErrors(
        std::move(EC),
        make_error<RawError>(raw_error_code::corrupt_file,
                             "Could not write linear map number of words"));

  uint32_t Idx = 0;
  for (uint32_t I = 0; I != ReqWords; ++I) {
    uint32_t Word = 0;
    for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) {
      if (Vec.test(Idx))
        Word |= (1 << WordIdx);
    }
    if (auto EC = Writer.writeInteger(Word))
      return joinErrors(std::move(EC), make_error<RawError>(
                                           raw_error_code::corrupt_file,
                                           "Could not write linear map word"));
  }
  return Error::success();
}
Example #3
0
Error DebugCrossModuleExportsSubsection::commit(
    BinaryStreamWriter &Writer) const {
  for (const auto &M : Mappings) {
    if (auto EC = Writer.writeInteger(M.first))
      return EC;
    if (auto EC = Writer.writeInteger(M.second))
      return EC;
  }
  return Error::success();
}
Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
  // Write a header
  PDBStringTableHeader H;
  H.Signature = PDBStringTableSignature;
  H.HashVersion = 1;
  H.ByteSize = Strings.calculateSerializedSize();
  if (auto EC = Writer.writeObject(H))
    return EC;
  assert(Writer.bytesRemaining() == 0);
  return Error::success();
}
Example #5
0
static void addPadding(BinaryStreamWriter &Writer) {
  uint32_t Align = Writer.getOffset() % 4;
  if (Align == 0)
    return;

  int PaddingBytes = 4 - Align;
  while (PaddingBytes > 0) {
    uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
    cantFail(Writer.writeInteger(Pad));
    --PaddingBytes;
  }
}
Example #6
0
static Error writeRecords(BinaryStreamWriter &Writer,
                          ArrayRef<CVSymbol> Records) {
  BinaryItemStream<CVSymbol> ItemStream(support::endianness::little);
  ItemStream.setItems(Records);
  BinaryStreamRef RecordsRef(ItemStream);
  return Writer.writeStreamRef(RecordsRef);
}
Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const {
  if (auto EC = Strings.commit(Writer))
    return EC;

  assert(Writer.bytesRemaining() == 0);
  return Error::success();
}
Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
                                         const msf::MSFLayout &MsfLayout,
                                         WritableBinaryStreamRef MsfBuffer) {
  // We write the Modi record to the `ModiWriter`, but we additionally write its
  // symbol stream to a brand new stream.
  if (auto EC = ModiWriter.writeObject(Layout))
    return EC;
  if (auto EC = ModiWriter.writeCString(ModuleName))
    return EC;
  if (auto EC = ModiWriter.writeCString(ObjFileName))
    return EC;
  if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
    return EC;

  if (Layout.ModDiStream != kInvalidStreamIndex) {
    auto NS = WritableMappedBlockStream::createIndexedStream(
        MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
    WritableBinaryStreamRef Ref(*NS);
    BinaryStreamWriter SymbolWriter(Ref);
    // Write the symbols.
    if (auto EC =
            SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
      return EC;
    BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little);
    Records.setItems(Symbols);
    BinaryStreamRef RecordsRef(Records);
    if (auto EC = SymbolWriter.writeStreamRef(RecordsRef))
      return EC;
    if (auto EC = SymbolWriter.padToAlignment(4))
      return EC;
    // TODO: Write C11 Line data
    assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
           "Invalid debug section alignment!");
    for (const auto &Builder : C13Builders) {
      assert(Builder && "Empty C13 Fragment Builder!");
      if (auto EC = Builder->commit(SymbolWriter))
        return EC;
    }

    // TODO: Figure out what GlobalRefs substream actually is and populate it.
    if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
      return EC;
    if (SymbolWriter.bytesRemaining() > 0)
      return make_error<RawError>(raw_error_code::stream_too_long);
  }
  return Error::success();
}
Example #9
0
Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) {
  GSIHashHeader Header;
  Header.VerSignature = GSIHashHeader::HdrSignature;
  Header.VerHdr = GSIHashHeader::HdrVersion;
  Header.HrSize = HashRecords.size() * sizeof(PSHashRecord);
  Header.NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4;

  if (auto EC = Writer.writeObject(Header))
    return EC;

  if (auto EC = Writer.writeArray(makeArrayRef(HashRecords)))
    return EC;
  if (auto EC = Writer.writeArray(makeArrayRef(HashBitmap)))
    return EC;
  if (auto EC = Writer.writeArray(makeArrayRef(HashBuckets)))
    return EC;
  return Error::success();
}
Example #10
0
Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const {
  assert(FinalizedInfo.hasValue());

  // The first field is the number of bytes of string data.
  if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes))
    return EC;

  for (const auto &Name : OrderedStreamNames) {
    auto Item = Mapping.find(Name);
    if (Item == Mapping.end())
      continue;
    if (auto EC = Writer.writeCString(Item->getKey()))
      return EC;
  }

  // And finally the Offset Index map.
  if (auto EC = FinalizedHashTable.commit(Writer))
    return EC;

  return Error::success();
}
Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
  BinaryStreamWriter SectionWriter;

  std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader));
  if (auto EC = writeHeader(SectionWriter))
    return EC;

  std::tie(SectionWriter, Writer) =
      Writer.split(Strings.calculateSerializedSize());
  if (auto EC = writeStrings(SectionWriter))
    return EC;

  std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize());
  if (auto EC = writeHashTable(SectionWriter))
    return EC;

  std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t));
  if (auto EC = writeEpilogue(SectionWriter))
    return EC;

  return Error::success();
}
Error DebugSymbolRVASubsection::commit(BinaryStreamWriter &Writer) const {
  return Writer.writeArray(makeArrayRef(RVAs));
}
Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const {
  if (auto EC = Writer.writeInteger<uint32_t>(Strings.size()))
    return EC;
  assert(Writer.bytesRemaining() == 0);
  return Error::success();
}