diff options
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/PDB/Native')
22 files changed, 731 insertions, 395 deletions
diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp index 897f78c51032..d765485bdb6d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp @@ -16,6 +16,7 @@  #include "llvm/DebugInfo/MSF/MSFCommon.h"  #include "llvm/DebugInfo/MSF/MappedBlockStream.h"  #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h" +#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"  #include "llvm/DebugInfo/PDB/Native/RawConstants.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/Support/BinaryItemStream.h" @@ -26,16 +27,6 @@ using namespace llvm::codeview;  using namespace llvm::msf;  using namespace llvm::pdb; -namespace llvm { -template <> struct BinaryItemTraits<CVSymbol> { -  static size_t length(const CVSymbol &Item) { return Item.RecordData.size(); } - -  static ArrayRef<uint8_t> bytes(const CVSymbol &Item) { -    return Item.RecordData; -  } -}; -} -  static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,                                              uint32_t C13Size) {    uint32_t Size = sizeof(uint32_t);   // Signature @@ -98,14 +89,6 @@ uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {    return alignTo(L + M + O, sizeof(uint32_t));  } -template <typename T> struct Foo { -  explicit Foo(T &&Answer) : Answer(Answer) {} - -  T Answer; -}; - -template <typename T> Foo<T> makeFoo(T &&t) { return Foo<T>(std::move(t)); } -  void DbiModuleDescriptorBuilder::finalize() {    Layout.SC.ModuleIndex = Layout.Mod;    Layout.FileNameOffs = 0; // TODO: Fix this diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index 0eeac7e4c084..04e6664c68db 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -12,7 +12,6 @@  #include "llvm/DebugInfo/MSF/MappedBlockStream.h"  #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"  #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h" -#include "llvm/DebugInfo/PDB/Native/InfoStream.h"  #include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawConstants.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h" diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp index 25076e40fc98..c96553ff9b16 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -49,6 +49,10 @@ void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {    SectionMap = SecMap;  } +void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) { +  GlobalsStreamIndex = Index; +} +  void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) {    SymRecordStreamIndex = Index;  } @@ -86,24 +90,9 @@ uint32_t DbiStreamBuilder::calculateSerializedLength() const {  Expected<DbiModuleDescriptorBuilder &>  DbiStreamBuilder::addModuleInfo(StringRef ModuleName) {    uint32_t Index = ModiList.size(); -  auto MIB = -      llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf); -  auto M = MIB.get(); -  auto Result = ModiMap.insert(std::make_pair(ModuleName, std::move(MIB))); - -  if (!Result.second) -    return make_error<RawError>(raw_error_code::duplicate_entry, -                                "The specified module already exists"); -  ModiList.push_back(M); -  return *M; -} - -Error DbiStreamBuilder::addModuleSourceFile(StringRef Module, StringRef File) { -  auto ModIter = ModiMap.find(Module); -  if (ModIter == ModiMap.end()) -    return make_error<RawError>(raw_error_code::no_entry, -                                "The specified module was not found"); -  return addModuleSourceFile(*ModIter->second, File); +  ModiList.push_back( +      llvm::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf)); +  return *ModiList.back();  }  Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module, @@ -270,7 +259,7 @@ Error DbiStreamBuilder::finalize() {    H->SymRecordStreamIndex = SymRecordStreamIndex;    H->PublicSymbolStreamIndex = PublicsStreamIndex;    H->MFCTypeServerIndex = kInvalidStreamIndex; -  H->GlobalSymbolStreamIndex = kInvalidStreamIndex; +  H->GlobalSymbolStreamIndex = GlobalsStreamIndex;    Header = H;    return Error::success(); @@ -307,19 +296,6 @@ static uint16_t toSecMapFlags(uint32_t Flags) {    return Ret;  } -void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi, -                                         const object::coff_section *SecHdr) { -  SectionContrib SC; -  memset(&SC, 0, sizeof(SC)); -  SC.ISect = (uint16_t)~0U; // This represents nil. -  SC.Off = SecHdr->PointerToRawData; -  SC.Size = SecHdr->SizeOfRawData; -  SC.Characteristics = SecHdr->Characteristics; -  // Use the module index in the module dbi stream or nil (-1). -  SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U; -  SectionContribs.emplace_back(SC); -} -  // A utility function to create a Section Map for a given list of COFF sections.  //  // A Section Map seem to be a copy of a COFF section list in other format. diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.cpp deleted file mode 100644 index b219fe275f73..000000000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.cpp +++ /dev/null @@ -1,93 +0,0 @@ -//===- GSI.cpp - Common Functions for GlobalsStream and PublicsStream  ----===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "GSI.h" - -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/BinaryStreamReader.h" - -#include "llvm/Support/Error.h" - -namespace llvm { -namespace pdb { - -static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) { -  if (HashHdr->VerHdr != GSIHashHeader::HdrVersion) -    return make_error<RawError>( -        raw_error_code::feature_unsupported, -        "Encountered unsupported globals stream version."); - -  return Error::success(); -} - -Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, -                         const GSIHashHeader *HashHdr, -                         BinaryStreamReader &Reader) { -  if (auto EC = checkHashHdrVersion(HashHdr)) -    return EC; - -  // Before the actual hash buckets, there is a bitmap of length determined by -  // IPHR_HASH. -  ArrayRef<uint8_t> Bitmap; -  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); -  uint32_t NumBitmapEntries = BitmapSizeInBits / 8; -  if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries)) -    return joinErrors(std::move(EC), -                      make_error<RawError>(raw_error_code::corrupt_file, -                                           "Could not read a bitmap.")); -  uint32_t NumBuckets = 0; -  for (uint8_t B : Bitmap) -    NumBuckets += countPopulation(B); - -  // Hash buckets follow. -  if (auto EC = Reader.readArray(HashBuckets, NumBuckets)) -    return joinErrors(std::move(EC), -                      make_error<RawError>(raw_error_code::corrupt_file, -                                           "Hash buckets corrupted.")); - -  return Error::success(); -} - -Error readGSIHashHeader(const GSIHashHeader *&HashHdr, -                        BinaryStreamReader &Reader) { -  if (Reader.readObject(HashHdr)) -    return make_error<RawError>(raw_error_code::corrupt_file, -                                "Stream does not contain a GSIHashHeader."); - -  if (HashHdr->VerSignature != GSIHashHeader::HdrSignature) -    return make_error<RawError>( -        raw_error_code::feature_unsupported, -        "GSIHashHeader signature (0xffffffff) not found."); - -  return Error::success(); -} - -Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, -                         const GSIHashHeader *HashHdr, -                         BinaryStreamReader &Reader) { -  if (auto EC = checkHashHdrVersion(HashHdr)) -    return EC; - -  // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have. -  // Verify that we can read them all. -  if (HashHdr->HrSize % sizeof(PSHashRecord)) -    return make_error<RawError>(raw_error_code::corrupt_file, -                                "Invalid HR array size."); -  uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord); -  if (auto EC = Reader.readArray(HashRecords, NumHashRecords)) -    return joinErrors(std::move(EC), -                      make_error<RawError>(raw_error_code::corrupt_file, -                                           "Error reading hash records.")); - -  return Error::success(); -} -} -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.h b/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.h deleted file mode 100644 index 9e63bc83548f..000000000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/GSI.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- GSI.h - Common Declarations for GlobalsStream and PublicsStream ----===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The data structures defined in this file are based on the reference -// implementation which is available at -// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h -// -// When you are reading the reference source code, you'd find the -// information below useful. -// -//  - ppdb1->m_fMinimalDbgInfo seems to be always true. -//  - SMALLBUCKETS macro is defined. -// -// The reference doesn't compile, so I learned just by reading code. -// It's not guaranteed to be correct. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H -#define LLVM_LIB_DEBUGINFO_PDB_RAW_GSI_H - -#include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/Support/BinaryStreamArray.h" - -#include "llvm/Support/Endian.h" -#include "llvm/Support/Error.h" - -namespace llvm { - -class BinaryStreamReader; - -namespace pdb { - -/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp -static const unsigned IPHR_HASH = 4096; - -/// Header of the hash tables found in the globals and publics sections. -/// Based on GSIHashHeader in -/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h -struct GSIHashHeader { -  enum : unsigned { -    HdrSignature = ~0U, -    HdrVersion = 0xeffe0000 + 19990810, -  }; -  support::ulittle32_t VerSignature; -  support::ulittle32_t VerHdr; -  support::ulittle32_t HrSize; -  support::ulittle32_t NumBuckets; -}; - -Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, -                         const GSIHashHeader *HashHdr, -                         BinaryStreamReader &Reader); -Error readGSIHashHeader(const GSIHashHeader *&HashHdr, -                        BinaryStreamReader &Reader); -Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, -                         const GSIHashHeader *HashHdr, -                         BinaryStreamReader &Reader); -} -} - -#endif diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp new file mode 100644 index 000000000000..e84f25dfeefa --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/GSIStreamBuilder.cpp @@ -0,0 +1,322 @@ +//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" + +#include "llvm/DebugInfo/CodeView/RecordName.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolSerializer.h" +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/Support/BinaryItemStream.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include <algorithm> +#include <vector> + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; +using namespace llvm::codeview; + +struct llvm::pdb::GSIHashStreamBuilder { +  std::vector<CVSymbol> Records; +  uint32_t StreamIndex; +  std::vector<PSHashRecord> HashRecords; +  std::array<support::ulittle32_t, (IPHR_HASH + 32) / 32> HashBitmap; +  std::vector<support::ulittle32_t> HashBuckets; + +  uint32_t calculateSerializedLength() const; +  uint32_t calculateRecordByteSize() const; +  Error commit(BinaryStreamWriter &Writer); +  void finalizeBuckets(uint32_t RecordZeroOffset); + +  template <typename T> void addSymbol(const T &Symbol, MSFBuilder &Msf) { +    T Copy(Symbol); +    Records.push_back(SymbolSerializer::writeOneSymbol(Copy, Msf.getAllocator(), +                                                       CodeViewContainer::Pdb)); +  } +  void addSymbol(const CVSymbol &Symbol) { Records.push_back(Symbol); } +}; + +uint32_t GSIHashStreamBuilder::calculateSerializedLength() const { +  uint32_t Size = sizeof(GSIHashHeader); +  Size += HashRecords.size() * sizeof(PSHashRecord); +  Size += HashBitmap.size() * sizeof(uint32_t); +  Size += HashBuckets.size() * sizeof(uint32_t); +  return Size; +} + +uint32_t GSIHashStreamBuilder::calculateRecordByteSize() const { +  uint32_t Size = 0; +  for (const auto &Sym : Records) +    Size += Sym.length(); +  return Size; +} + +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(); +} + +void GSIHashStreamBuilder::finalizeBuckets(uint32_t RecordZeroOffset) { +  std::array<std::vector<PSHashRecord>, IPHR_HASH + 1> TmpBuckets; +  uint32_t SymOffset = RecordZeroOffset; +  for (const CVSymbol &Sym : Records) { +    PSHashRecord HR; +    // Add one when writing symbol offsets to disk. See GSI1::fixSymRecs. +    HR.Off = SymOffset + 1; +    HR.CRef = 1; // Always use a refcount of 1. + +    // Hash the name to figure out which bucket this goes into. +    StringRef Name = getSymbolName(Sym); +    size_t BucketIdx = hashStringV1(Name) % IPHR_HASH; +    TmpBuckets[BucketIdx].push_back(HR); // FIXME: Does order matter? + +    SymOffset += Sym.length(); +  } + +  // Compute the three tables: the hash records in bucket and chain order, the +  // bucket presence bitmap, and the bucket chain start offsets. +  HashRecords.reserve(Records.size()); +  for (ulittle32_t &Word : HashBitmap) +    Word = 0; +  for (size_t BucketIdx = 0; BucketIdx < IPHR_HASH + 1; ++BucketIdx) { +    auto &Bucket = TmpBuckets[BucketIdx]; +    if (Bucket.empty()) +      continue; +    HashBitmap[BucketIdx / 32] |= 1U << (BucketIdx % 32); + +    // Calculate what the offset of the first hash record in the chain would +    // be if it were inflated to contain 32-bit pointers. On a 32-bit system, +    // each record would be 12 bytes. See HROffsetCalc in gsi.h. +    const int SizeOfHROffsetCalc = 12; +    ulittle32_t ChainStartOff = +        ulittle32_t(HashRecords.size() * SizeOfHROffsetCalc); +    HashBuckets.push_back(ChainStartOff); +    for (const auto &HR : Bucket) +      HashRecords.push_back(HR); +  } +} + +GSIStreamBuilder::GSIStreamBuilder(msf::MSFBuilder &Msf) +    : Msf(Msf), PSH(llvm::make_unique<GSIHashStreamBuilder>()), +      GSH(llvm::make_unique<GSIHashStreamBuilder>()) {} + +GSIStreamBuilder::~GSIStreamBuilder() {} + +uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize() const { +  uint32_t Size = 0; +  Size += sizeof(PublicsStreamHeader); +  Size += PSH->calculateSerializedLength(); +  Size += PSH->Records.size() * sizeof(uint32_t); // AddrMap +  // FIXME: Add thunk map and section offsets for incremental linking. + +  return Size; +} + +uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize() const { +  return GSH->calculateSerializedLength(); +} + +Error GSIStreamBuilder::finalizeMsfLayout() { +  // First we write public symbol records, then we write global symbol records. +  uint32_t PSHZero = 0; +  uint32_t GSHZero = PSH->calculateRecordByteSize(); + +  PSH->finalizeBuckets(PSHZero); +  GSH->finalizeBuckets(GSHZero); + +  Expected<uint32_t> Idx = Msf.addStream(calculatePublicsHashStreamSize()); +  if (!Idx) +    return Idx.takeError(); +  PSH->StreamIndex = *Idx; +  Idx = Msf.addStream(calculateGlobalsHashStreamSize()); +  if (!Idx) +    return Idx.takeError(); +  GSH->StreamIndex = *Idx; + +  uint32_t RecordBytes = +      GSH->calculateRecordByteSize() + PSH->calculateRecordByteSize(); + +  Idx = Msf.addStream(RecordBytes); +  if (!Idx) +    return Idx.takeError(); +  RecordStreamIdx = *Idx; +  return Error::success(); +} + +static bool comparePubSymByAddrAndName( +    const std::pair<const CVSymbol *, const PublicSym32 *> &LS, +    const std::pair<const CVSymbol *, const PublicSym32 *> &RS) { +  if (LS.second->Segment != RS.second->Segment) +    return LS.second->Segment < RS.second->Segment; +  if (LS.second->Offset != RS.second->Offset) +    return LS.second->Offset < RS.second->Offset; + +  return LS.second->Name < RS.second->Name; +} + +/// Compute the address map. The address map is an array of symbol offsets +/// sorted so that it can be binary searched by address. +static std::vector<ulittle32_t> computeAddrMap(ArrayRef<CVSymbol> Records) { +  // Make a vector of pointers to the symbols so we can sort it by address. +  // Also gather the symbol offsets while we're at it. + +  std::vector<PublicSym32> DeserializedPublics; +  std::vector<std::pair<const CVSymbol *, const PublicSym32 *>> PublicsByAddr; +  std::vector<uint32_t> SymOffsets; +  DeserializedPublics.reserve(Records.size()); +  PublicsByAddr.reserve(Records.size()); +  SymOffsets.reserve(Records.size()); + +  uint32_t SymOffset = 0; +  for (const CVSymbol &Sym : Records) { +    assert(Sym.kind() == SymbolKind::S_PUB32); +    DeserializedPublics.push_back( +        cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym))); +    PublicsByAddr.emplace_back(&Sym, &DeserializedPublics.back()); +    SymOffsets.push_back(SymOffset); +    SymOffset += Sym.length(); +  } +  std::stable_sort(PublicsByAddr.begin(), PublicsByAddr.end(), +                   comparePubSymByAddrAndName); + +  // Fill in the symbol offsets in the appropriate order. +  std::vector<ulittle32_t> AddrMap; +  AddrMap.reserve(Records.size()); +  for (auto &Sym : PublicsByAddr) { +    ptrdiff_t Idx = std::distance(Records.data(), Sym.first); +    assert(Idx >= 0 && size_t(Idx) < Records.size()); +    AddrMap.push_back(ulittle32_t(SymOffsets[Idx])); +  } +  return AddrMap; +} + +uint32_t GSIStreamBuilder::getPublicsStreamIndex() const { +  return PSH->StreamIndex; +} + +uint32_t GSIStreamBuilder::getGlobalsStreamIndex() const { +  return GSH->StreamIndex; +} + +void GSIStreamBuilder::addPublicSymbol(const PublicSym32 &Pub) { +  PSH->addSymbol(Pub, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const ProcRefSym &Sym) { +  GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const DataSym &Sym) { +  GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const ConstantSym &Sym) { +  GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const UDTSym &Sym) { +  GSH->addSymbol(Sym, Msf); +} + +void GSIStreamBuilder::addGlobalSymbol(const codeview::CVSymbol &Sym) { +  GSH->addSymbol(Sym); +} + +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 GSIStreamBuilder::commitSymbolRecordStream( +    WritableBinaryStreamRef Stream) { +  BinaryStreamWriter Writer(Stream); + +  // Write public symbol records first, followed by global symbol records.  This +  // must match the order that we assume in finalizeMsfLayout when computing +  // PSHZero and GSHZero. +  if (auto EC = writeRecords(Writer, PSH->Records)) +    return EC; +  if (auto EC = writeRecords(Writer, GSH->Records)) +    return EC; + +  return Error::success(); +} + +Error GSIStreamBuilder::commitPublicsHashStream( +    WritableBinaryStreamRef Stream) { +  BinaryStreamWriter Writer(Stream); +  PublicsStreamHeader Header; + +  // FIXME: Fill these in. They are for incremental linking. +  Header.NumThunks = 0; +  Header.SizeOfThunk = 0; +  Header.ISectThunkTable = 0; +  Header.OffThunkTable = 0; +  Header.NumSections = 0; +  Header.SymHash = PSH->calculateSerializedLength(); +  Header.AddrMap = PSH->Records.size() * 4; +  if (auto EC = Writer.writeObject(Header)) +    return EC; + +  if (auto EC = PSH->commit(Writer)) +    return EC; + +  std::vector<ulittle32_t> AddrMap = computeAddrMap(PSH->Records); +  if (auto EC = Writer.writeArray(makeArrayRef(AddrMap))) +    return EC; + +  return Error::success(); +} + +Error GSIStreamBuilder::commitGlobalsHashStream( +    WritableBinaryStreamRef Stream) { +  BinaryStreamWriter Writer(Stream); +  return GSH->commit(Writer); +} + +Error GSIStreamBuilder::commit(const msf::MSFLayout &Layout, +                               WritableBinaryStreamRef Buffer) { +  auto GS = WritableMappedBlockStream::createIndexedStream( +      Layout, Buffer, getGlobalsStreamIndex(), Msf.getAllocator()); +  auto PS = WritableMappedBlockStream::createIndexedStream( +      Layout, Buffer, getPublicsStreamIndex(), Msf.getAllocator()); +  auto PRS = WritableMappedBlockStream::createIndexedStream( +      Layout, Buffer, getRecordStreamIdx(), Msf.getAllocator()); + +  if (auto EC = commitSymbolRecordStream(*PRS)) +    return EC; +  if (auto EC = commitGlobalsHashStream(*GS)) +    return EC; +  if (auto EC = commitPublicsHashStream(*PS)) +    return EC; +  return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp index a2ee0f047c58..36076f436ad0 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/GlobalsStream.cpp @@ -1,4 +1,4 @@ -//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---- ----*- C++ -*-===// +//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---------*- C++ -*-===//  //  //                     The LLVM Compiler Infrastructure  // @@ -6,9 +6,21 @@  // License. See LICENSE.TXT for details.  //  //===----------------------------------------------------------------------===// +// +// The on-disk structores used in this file are based on the reference +// implementation which is available at +// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h +// +// When you are reading the reference source code, you'd find the +// information below useful. +// +//  - ppdb1->m_fMinimalDbgInfo seems to be always true. +//  - SMALLBUCKETS macro is defined. +// +//===----------------------------------------------------------------------===//  #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" -#include "GSI.h" +#include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/Support/BinaryStreamReader.h"  #include "llvm/Support/Error.h"  #include <algorithm> @@ -24,19 +36,89 @@ GlobalsStream::~GlobalsStream() = default;  Error GlobalsStream::reload() {    BinaryStreamReader Reader(*Stream); +  if (auto E = GlobalsTable.read(Reader)) +    return E; +  return Error::success(); +} -  const GSIHashHeader *HashHdr; -  if (auto EC = readGSIHashHeader(HashHdr, Reader)) -    return EC; +static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) { +  if (HashHdr->VerHdr != GSIHashHeader::HdrVersion) +    return make_error<RawError>( +        raw_error_code::feature_unsupported, +        "Encountered unsupported globals stream version."); -  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader)) +  return Error::success(); +} + +static Error readGSIHashHeader(const GSIHashHeader *&HashHdr, +                               BinaryStreamReader &Reader) { +  if (Reader.readObject(HashHdr)) +    return make_error<RawError>(raw_error_code::corrupt_file, +                                "Stream does not contain a GSIHashHeader."); + +  if (HashHdr->VerSignature != GSIHashHeader::HdrSignature) +    return make_error<RawError>( +        raw_error_code::feature_unsupported, +        "GSIHashHeader signature (0xffffffff) not found."); + +  return Error::success(); +} + +static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, +                                const GSIHashHeader *HashHdr, +                                BinaryStreamReader &Reader) { +  if (auto EC = checkHashHdrVersion(HashHdr))      return EC; -  if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader)) +  // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have. +  // Verify that we can read them all. +  if (HashHdr->HrSize % sizeof(PSHashRecord)) +    return make_error<RawError>(raw_error_code::corrupt_file, +                                "Invalid HR array size."); +  uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord); +  if (auto EC = Reader.readArray(HashRecords, NumHashRecords)) +    return joinErrors(std::move(EC), +                      make_error<RawError>(raw_error_code::corrupt_file, +                                           "Error reading hash records.")); + +  return Error::success(); +} + +static Error +readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, +                   ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr, +                   BinaryStreamReader &Reader) { +  if (auto EC = checkHashHdrVersion(HashHdr))      return EC; -  NumBuckets = HashBuckets.size(); + +  // Before the actual hash buckets, there is a bitmap of length determined by +  // IPHR_HASH. +  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); +  uint32_t NumBitmapEntries = BitmapSizeInBits / 8; +  if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries)) +    return joinErrors(std::move(EC), +                      make_error<RawError>(raw_error_code::corrupt_file, +                                           "Could not read a bitmap.")); +  uint32_t NumBuckets = 0; +  for (uint8_t B : HashBitmap) +    NumBuckets += countPopulation(B); + +  // Hash buckets follow. +  if (auto EC = Reader.readArray(HashBuckets, NumBuckets)) +    return joinErrors(std::move(EC), +                      make_error<RawError>(raw_error_code::corrupt_file, +                                           "Hash buckets corrupted."));    return Error::success();  } -Error GlobalsStream::commit() { return Error::success(); } +Error GSIHashTable::read(BinaryStreamReader &Reader) { +  if (auto EC = readGSIHashHeader(HashHdr, Reader)) +    return EC; +  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader)) +    return EC; +  if (HashHdr->HrSize > 0) +    if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader)) +      return EC; +  return Error::success(); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp index 829879060c33..17c9392a9dd5 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/InfoStream.cpp @@ -10,12 +10,10 @@  #include "llvm/DebugInfo/PDB/Native/InfoStream.h"  #include "llvm/ADT/BitVector.h"  #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawConstants.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/DebugInfo/PDB/Native/RawTypes.h"  #include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamWriter.h"  using namespace llvm;  using namespace llvm::codeview; diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp index 60416f69e137..4644ddcf24e3 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeBuiltinSymbol.cpp @@ -9,7 +9,6 @@  #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" -#include "llvm/DebugInfo/PDB/Native/NativeSession.h"  namespace llvm {  namespace pdb { diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp new file mode 100644 index 000000000000..38d65917306a --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumSymbol.cpp @@ -0,0 +1,108 @@ +//===- NativeEnumSymbol.cpp - info about enum type --------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" + +#include <cassert> + +using namespace llvm; +using namespace llvm::pdb; + +NativeEnumSymbol::NativeEnumSymbol(NativeSession &Session, SymIndexId Id, +                                   const codeview::CVType &CVT) +    : NativeRawSymbol(Session, Id), CV(CVT), +      Record(codeview::TypeRecordKind::Enum) { +  assert(CV.kind() == codeview::TypeLeafKind::LF_ENUM); +  cantFail(visitTypeRecord(CV, *this)); +} + +NativeEnumSymbol::~NativeEnumSymbol() {} + +std::unique_ptr<NativeRawSymbol> NativeEnumSymbol::clone() const { +  return llvm::make_unique<NativeEnumSymbol>(Session, SymbolId, CV); +} + +std::unique_ptr<IPDBEnumSymbols> +NativeEnumSymbol::findChildren(PDB_SymType Type) const { +  switch (Type) { +  case PDB_SymType::Data: { +    // TODO(amccarth):  Provide an actual implementation. +    return nullptr; +  } +  default: +    return nullptr; +  } +} + +Error NativeEnumSymbol::visitKnownRecord(codeview::CVType &CVR, +                                         codeview::EnumRecord &ER) { +  Record = ER; +  return Error::success(); +} + +Error NativeEnumSymbol::visitKnownMember(codeview::CVMemberRecord &CVM, +                                         codeview::EnumeratorRecord &R) { +  return Error::success(); +} + +PDB_SymType NativeEnumSymbol::getSymTag() const { return PDB_SymType::Enum; } + +uint32_t NativeEnumSymbol::getClassParentId() const { return 0xFFFFFFFF; } + +uint32_t NativeEnumSymbol::getUnmodifiedTypeId() const { return 0; } + +bool NativeEnumSymbol::hasConstructor() const { +  return bool(Record.getOptions() & +              codeview::ClassOptions::HasConstructorOrDestructor); +} + +bool NativeEnumSymbol::hasAssignmentOperator() const { +  return bool(Record.getOptions() & +              codeview::ClassOptions::HasOverloadedAssignmentOperator); +} + +bool NativeEnumSymbol::hasCastOperator() const { +  return bool(Record.getOptions() & +              codeview::ClassOptions::HasConversionOperator); +} + +uint64_t NativeEnumSymbol::getLength() const { +  const auto Id = Session.findSymbolByTypeIndex(Record.getUnderlyingType()); +  const auto UnderlyingType = +      Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(Id); +  return UnderlyingType ? UnderlyingType->getLength() : 0; +} + +std::string NativeEnumSymbol::getName() const { return Record.getName(); } + +bool NativeEnumSymbol::isNested() const { +  return bool(Record.getOptions() & codeview::ClassOptions::Nested); +} + +bool NativeEnumSymbol::hasOverloadedOperator() const { +  return bool(Record.getOptions() & +              codeview::ClassOptions::HasOverloadedOperator); +} + +bool NativeEnumSymbol::isPacked() const { +  return bool(Record.getOptions() & codeview::ClassOptions::Packed); +} + +bool NativeEnumSymbol::isScoped() const { +  return bool(Record.getOptions() & codeview::ClassOptions::Scoped); +} + +uint32_t NativeEnumSymbol::getTypeId() const { +  return Session.findSymbolByTypeIndex(Record.getUnderlyingType()); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp new file mode 100644 index 000000000000..36a68a1c62de --- /dev/null +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeEnumTypes.cpp @@ -0,0 +1,59 @@ +//==- NativeEnumTypes.cpp - Native Type Enumerator impl ----------*- C++ -*-==// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeSession.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" + +namespace llvm { +namespace pdb { + +NativeEnumTypes::NativeEnumTypes(NativeSession &PDBSession, +                                 codeview::LazyRandomTypeCollection &Types, +                                 codeview::TypeLeafKind Kind) +    : Matches(), Index(0), Session(PDBSession), Kind(Kind) { +  for (auto Index = Types.getFirst(); Index; +       Index = Types.getNext(Index.getValue())) { +    if (Types.getType(Index.getValue()).kind() == Kind) +      Matches.push_back(Index.getValue()); +  } +} + +NativeEnumTypes::NativeEnumTypes( +    NativeSession &PDBSession, const std::vector<codeview::TypeIndex> &Matches, +    codeview::TypeLeafKind Kind) +    : Matches(Matches), Index(0), Session(PDBSession), Kind(Kind) {} + +uint32_t NativeEnumTypes::getChildCount() const { +  return static_cast<uint32_t>(Matches.size()); +} + +std::unique_ptr<PDBSymbol> +NativeEnumTypes::getChildAtIndex(uint32_t Index) const { +  if (Index < Matches.size()) +    return Session.createEnumSymbol(Matches[Index]); +  return nullptr; +} + +std::unique_ptr<PDBSymbol> NativeEnumTypes::getNext() { +  return getChildAtIndex(Index++); +} + +void NativeEnumTypes::reset() { Index = 0; } + +NativeEnumTypes *NativeEnumTypes::clone() const { +  return new NativeEnumTypes(Session, Matches, Kind); +} + +} // namespace pdb +} // namespace llvm diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp index 3241000b06db..e8b06065fc60 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeExeSymbol.cpp @@ -38,6 +38,8 @@ NativeExeSymbol::findChildren(PDB_SymType Type) const {      consumeError(Dbi.takeError());      break;    } +  case PDB_SymType::Enum: +    return Session.createTypeEnumerator(codeview::LF_ENUM);    default:      break;    } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp index df3f418052a9..d23ee0a09196 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeRawSymbol.cpp @@ -286,6 +286,11 @@ std::string NativeRawSymbol::getUndecoratedName() const {    return {};  } +std::string NativeRawSymbol::getUndecoratedNameEx( +    PDB_UndnameFlags Flags) const { +  return {}; +} +  uint32_t NativeRawSymbol::getUnmodifiedTypeId() const {    return 0;  } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp index 76de0d8f9e7e..b01c2b54796c 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -16,11 +16,15 @@  #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"  #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"  #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"  #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h"  #include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h" +#include "llvm/DebugInfo/PDB/Native/TpiStream.h"  #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"  #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"  #include "llvm/Support/Allocator.h"  #include "llvm/Support/BinaryByteStream.h"  #include "llvm/Support/Error.h" @@ -28,6 +32,7 @@  #include "llvm/Support/MemoryBuffer.h"  #include <algorithm> +#include <cassert>  #include <memory>  #include <utility> @@ -63,15 +68,9 @@ NativeSession::NativeSession(std::unique_ptr<PDBFile> PdbFile,  NativeSession::~NativeSession() = default; -Error NativeSession::createFromPdb(StringRef Path, +Error NativeSession::createFromPdb(std::unique_ptr<MemoryBuffer> Buffer,                                     std::unique_ptr<IPDBSession> &Session) { -  ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer = -      MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, -                                   /*RequiresNullTerminator=*/false); -  if (!ErrorOrBuffer) -    return make_error<GenericError>(generic_error_code::invalid_path); - -  std::unique_ptr<MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); +  StringRef Path = Buffer->getBufferIdentifier();    auto Stream = llvm::make_unique<MemoryBufferByteStream>(        std::move(Buffer), llvm::support::little); @@ -102,6 +101,25 @@ NativeSession::createCompilandSymbol(DbiModuleDescriptor MI) {        *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone()));  } +std::unique_ptr<PDBSymbolTypeEnum> +NativeSession::createEnumSymbol(codeview::TypeIndex Index) { +  const auto Id = findSymbolByTypeIndex(Index); +  return llvm::make_unique<PDBSymbolTypeEnum>( +      *this, std::unique_ptr<IPDBRawSymbol>(SymbolCache[Id]->clone())); +} + +std::unique_ptr<IPDBEnumSymbols> +NativeSession::createTypeEnumerator(codeview::TypeLeafKind Kind) { +  auto Tpi = Pdb->getPDBTpiStream(); +  if (!Tpi) { +    consumeError(Tpi.takeError()); +    return nullptr; +  } +  auto &Types = Tpi->typeCollection(); +  return std::unique_ptr<IPDBEnumSymbols>( +      new NativeEnumTypes(*this, Types, codeview::LF_ENUM)); +} +  SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {    // First see if it's already in our cache.    const auto Entry = TypeIndexToSymbolId.find(Index); @@ -129,9 +147,20 @@ SymIndexId NativeSession::findSymbolByTypeIndex(codeview::TypeIndex Index) {      return Id;    } -  // TODO:  Look up PDB type by type index - -  return 0; +  // We need to instantiate and cache the desired type symbol. +  auto Tpi = Pdb->getPDBTpiStream(); +  if (!Tpi) { +    consumeError(Tpi.takeError()); +    return 0; +  } +  auto &Types = Tpi->typeCollection(); +  const auto &I = Types.getType(Index); +  const auto Id = static_cast<SymIndexId>(SymbolCache.size()); +  // TODO(amccarth):  Make this handle all types, not just LF_ENUMs. +  assert(I.kind() == codeview::LF_ENUM); +  SymbolCache.emplace_back(llvm::make_unique<NativeEnumSymbol>(*this, Id, I)); +  TypeIndexToSymbolId[Index] = Id; +  return Id;  }  uint64_t NativeSession::getLoadAddress() const { return 0; } @@ -216,3 +245,7 @@ NativeSession::getSourceFileById(uint32_t FileId) const {  std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {    return nullptr;  } + +std::unique_ptr<IPDBEnumTables> NativeSession::getEnumTables() const { +  return nullptr; +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 0b6492efc70f..15b31d821b1c 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -85,6 +85,11 @@ uint32_t PDBFile::getNumStreams() const {    return ContainerLayout.StreamSizes.size();  } +uint32_t PDBFile::getMaxStreamSize() const { +  return *std::max_element(ContainerLayout.StreamSizes.begin(), +                           ContainerLayout.StreamSizes.end()); +} +  uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {    return ContainerLayout.StreamSizes[StreamIndex];  } @@ -150,8 +155,7 @@ Error PDBFile::parseFileHeaders() {        MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator);    BinaryStreamReader FpmReader(*FpmStream);    ArrayRef<uint8_t> FpmBytes; -  if (auto EC = FpmReader.readBytes(FpmBytes, -                                    msf::getFullFpmByteSize(ContainerLayout))) +  if (auto EC = FpmReader.readBytes(FpmBytes, FpmReader.bytesRemaining()))      return EC;    uint32_t BlocksRemaining = getBlockCount();    uint32_t BI = 0; @@ -230,6 +234,13 @@ ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {    return ContainerLayout.DirectoryBlocks;  } +std::unique_ptr<MappedBlockStream> PDBFile::createIndexedStream(uint16_t SN) { +  if (SN == kInvalidStreamIndex) +    return nullptr; +  return MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, SN, +                                                Allocator); +} +  MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const {    MSFStreamLayout Result;    auto Blocks = getStreamBlockList(StreamIdx); @@ -238,6 +249,10 @@ MSFStreamLayout PDBFile::getStreamLayout(uint32_t StreamIdx) const {    return Result;  } +msf::MSFStreamLayout PDBFile::getFpmStreamLayout() const { +  return msf::getFpmStreamLayout(ContainerLayout); +} +  Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {    if (!Globals) {      auto DbiS = getPDBDbiStream(); @@ -297,6 +312,9 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() {  Expected<TpiStream &> PDBFile::getPDBIpiStream() {    if (!Ipi) { +    if (!hasPDBIpiStream()) +      return make_error<RawError>(raw_error_code::no_stream); +      auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI);      if (!IpiS)        return IpiS.takeError(); @@ -318,8 +336,7 @@ Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {          ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());      if (!PublicS)        return PublicS.takeError(); -    auto TempPublics = -        llvm::make_unique<PublicsStream>(*this, std::move(*PublicS)); +    auto TempPublics = llvm::make_unique<PublicsStream>(std::move(*PublicS));      if (auto EC = TempPublics->reload())        return std::move(EC);      Publics = std::move(TempPublics); @@ -393,9 +410,18 @@ bool PDBFile::hasPDBGlobalsStream() {    return DbiS->getGlobalSymbolStreamIndex() < getNumStreams();  } -bool PDBFile::hasPDBInfoStream() { return StreamPDB < getNumStreams(); } +bool PDBFile::hasPDBInfoStream() const { return StreamPDB < getNumStreams(); } + +bool PDBFile::hasPDBIpiStream() const { +  if (!hasPDBInfoStream()) +    return false; + +  if (StreamIPI >= getNumStreams()) +    return false; -bool PDBFile::hasPDBIpiStream() const { return StreamIPI < getNumStreams(); } +  auto &InfoStream = cantFail(const_cast<PDBFile *>(this)->getPDBInfoStream()); +  return InfoStream.containsIdStream(); +}  bool PDBFile::hasPDBPublicsStream() {    auto DbiS = getPDBDbiStream(); diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 9f35fd73629c..dee27c621fac 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -15,10 +15,10 @@  #include "llvm/DebugInfo/PDB/GenericError.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/PDBStringTableBuilder.h" -#include "llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/DebugInfo/PDB/Native/TpiStream.h"  #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" @@ -74,10 +74,10 @@ PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {    return Strings;  } -PublicsStreamBuilder &PDBFileBuilder::getPublicsBuilder() { -  if (!Publics) -    Publics = llvm::make_unique<PublicsStreamBuilder>(*Msf); -  return *Publics; +GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() { +  if (!Gsi) +    Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf); +  return *Gsi;  }  Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { @@ -122,12 +122,13 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {      if (auto EC = Ipi->finalizeMsfLayout())        return std::move(EC);    } -  if (Publics) { -    if (auto EC = Publics->finalizeMsfLayout()) +  if (Gsi) { +    if (auto EC = Gsi->finalizeMsfLayout())        return std::move(EC);      if (Dbi) { -      Dbi->setPublicsStreamIndex(Publics->getStreamIndex()); -      Dbi->setSymbolRecordStreamIndex(Publics->getRecordStreamIdx()); +      Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex()); +      Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex()); +      Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());      }    } @@ -141,6 +142,31 @@ Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {    return SN;  } +void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer, +                               const MSFLayout &Layout) { +  auto FpmStream = +      WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator); + +  // We only need to create the alt fpm stream so that it gets initialized. +  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator, +                                             true); + +  uint32_t BI = 0; +  BinaryStreamWriter FpmWriter(*FpmStream); +  while (BI < Layout.SB->NumBlocks) { +    uint8_t ThisByte = 0; +    for (uint32_t I = 0; I < 8; ++I) { +      bool IsFree = +          (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true; +      uint8_t Mask = uint8_t(IsFree) << I; +      ThisByte |= Mask; +      ++BI; +    } +    cantFail(FpmWriter.writeObject(ThisByte)); +  } +  assert(FpmWriter.bytesRemaining() == 0); +} +  Error PDBFileBuilder::commit(StringRef Filename) {    assert(!Filename.empty());    auto ExpectedLayout = finalizeMsfLayout(); @@ -150,15 +176,17 @@ Error PDBFileBuilder::commit(StringRef Filename) {    uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;    auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize); -  if (OutFileOrError.getError()) -    return llvm::make_error<pdb::GenericError>(generic_error_code::invalid_path, -                                               Filename); +  if (auto E = OutFileOrError.takeError()) +    return E;    FileBufferByteStream Buffer(std::move(*OutFileOrError),                                llvm::support::little);    BinaryStreamWriter Writer(Buffer);    if (auto EC = Writer.writeObject(*Layout.SB))      return EC; + +  commitFpm(Buffer, Layout); +    uint32_t BlockMapOffset =        msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);    Writer.setOffset(BlockMapOffset); @@ -209,11 +237,8 @@ Error PDBFileBuilder::commit(StringRef Filename) {        return EC;    } -  if (Publics) { -    auto PS = WritableMappedBlockStream::createIndexedStream( -        Layout, Buffer, Publics->getStreamIndex(), Allocator); -    BinaryStreamWriter PSWriter(*PS); -    if (auto EC = Publics->commit(PSWriter)) +  if (Gsi) { +    if (auto EC = Gsi->commit(Layout, Buffer))        return EC;    } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index acd45f7a6219..f1c10357132b 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -10,7 +10,6 @@  #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"  #include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h"  #include "llvm/DebugInfo/PDB/Native/Hash.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/DebugInfo/PDB/Native/RawTypes.h" diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index 90acfadd311f..ece3e00b1a87 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -10,9 +10,7 @@  #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"  #include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h"  #include "llvm/DebugInfo/PDB/Native/Hash.h" -#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"  #include "llvm/DebugInfo/PDB/Native/RawTypes.h"  #include "llvm/Support/BinaryStreamWriter.h"  #include "llvm/Support/Endian.h" diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index 9c3e654f808b..f6466eb80464 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -23,13 +23,10 @@  //===----------------------------------------------------------------------===//  #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" -#include "GSI.h"  #include "llvm/ADT/iterator_range.h"  #include "llvm/DebugInfo/CodeView/SymbolRecord.h"  #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"  #include "llvm/Support/BinaryStreamReader.h"  #include "llvm/Support/Endian.h"  #include "llvm/Support/Error.h" @@ -41,14 +38,18 @@ using namespace llvm::msf;  using namespace llvm::support;  using namespace llvm::pdb; -PublicsStream::PublicsStream(PDBFile &File, -                             std::unique_ptr<MappedBlockStream> Stream) -    : Pdb(File), Stream(std::move(Stream)) {} +PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream) +    : Stream(std::move(Stream)) {}  PublicsStream::~PublicsStream() = default;  uint32_t PublicsStream::getSymHash() const { return Header->SymHash; } -uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; } +uint16_t PublicsStream::getThunkTableSection() const { +  return Header->ISectThunkTable; +} +uint32_t PublicsStream::getThunkTableOffset() const { +  return Header->OffThunkTable; +}  // Publics stream contains fixed-size headers and a serialized hash table.  // This implementation is not complete yet. It reads till the end of the @@ -64,20 +65,14 @@ Error PublicsStream::reload() {      return make_error<RawError>(raw_error_code::corrupt_file,                                  "Publics Stream does not contain a header."); -  // Read PSGSIHDR and GSIHashHdr structs. +  // Read PSGSIHDR struct.    if (Reader.readObject(Header))      return make_error<RawError>(raw_error_code::corrupt_file,                                  "Publics Stream does not contain a header."); -  if (auto EC = readGSIHashHeader(HashHdr, Reader)) -    return EC; - -  if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader)) -    return EC; - -  if (auto EC = readGSIHashBuckets(HashBuckets, HashHdr, Reader)) -    return EC; -  NumBuckets = HashBuckets.size(); +  // Read the hash table. +  if (auto E = PublicsTable.read(Reader)) +    return E;    // Something called "address map" follows.    uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t); @@ -105,26 +100,3 @@ Error PublicsStream::reload() {                                  "Corrupted publics stream.");    return Error::success();  } - -iterator_range<codeview::CVSymbolArray::Iterator> -PublicsStream::getSymbols(bool *HadError) const { -  auto SymbolS = Pdb.getPDBSymbolStream(); -  if (SymbolS.takeError()) { -    codeview::CVSymbolArray::Iterator Iter; -    return make_range(Iter, Iter); -  } -  SymbolStream &SS = SymbolS.get(); - -  return SS.getSymbols(HadError); -} - -Expected<const codeview::CVSymbolArray &> -PublicsStream::getSymbolArray() const { -  auto SymbolS = Pdb.getPDBSymbolStream(); -  if (!SymbolS) -    return SymbolS.takeError(); - -  return SymbolS->getSymbolArray(); -} - -Error PublicsStream::commit() { return Error::success(); } diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp deleted file mode 100644 index 28c4a8fc35d9..000000000000 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/PublicsStreamBuilder.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h" - -#include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/MSF/MSFCommon.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" - -#include "GSI.h" - -using namespace llvm; -using namespace llvm::msf; -using namespace llvm::pdb; - -PublicsStreamBuilder::PublicsStreamBuilder(msf::MSFBuilder &Msf) : Msf(Msf) {} - -PublicsStreamBuilder::~PublicsStreamBuilder() {} - -uint32_t PublicsStreamBuilder::calculateSerializedLength() const { -  uint32_t Size = 0; -  Size += sizeof(PublicsStreamHeader); -  Size += sizeof(GSIHashHeader); -  Size += HashRecords.size() * sizeof(PSHashRecord); -  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); -  uint32_t NumBitmapEntries = BitmapSizeInBits / 8; -  Size += NumBitmapEntries; - -  // FIXME: Account for hash buckets.  For now since we we write a zero-bitmap -  // indicating that no hash buckets are valid, we also write zero byets of hash -  // bucket data. -  Size += 0; -  return Size; -} - -Error PublicsStreamBuilder::finalizeMsfLayout() { -  Expected<uint32_t> Idx = Msf.addStream(calculateSerializedLength()); -  if (!Idx) -    return Idx.takeError(); -  StreamIdx = *Idx; - -  Expected<uint32_t> RecordIdx = Msf.addStream(0); -  if (!RecordIdx) -    return RecordIdx.takeError(); -  RecordStreamIdx = *RecordIdx; -  return Error::success(); -} - -Error PublicsStreamBuilder::commit(BinaryStreamWriter &PublicsWriter) { -  PublicsStreamHeader PSH; -  GSIHashHeader GSH; - -  // FIXME: Figure out what to put for these values. -  PSH.AddrMap = 0; -  PSH.ISectThunkTable = 0; -  PSH.NumSections = 0; -  PSH.NumThunks = 0; -  PSH.OffThunkTable = 0; -  PSH.SizeOfThunk = 0; -  PSH.SymHash = 0; - -  GSH.VerSignature = GSIHashHeader::HdrSignature; -  GSH.VerHdr = GSIHashHeader::HdrVersion; -  GSH.HrSize = 0; -  GSH.NumBuckets = 0; - -  if (auto EC = PublicsWriter.writeObject(PSH)) -    return EC; -  if (auto EC = PublicsWriter.writeObject(GSH)) -    return EC; -  if (auto EC = PublicsWriter.writeArray(makeArrayRef(HashRecords))) -    return EC; - -  size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); -  uint32_t NumBitmapEntries = BitmapSizeInBits / 8; -  std::vector<uint8_t> BitmapData(NumBitmapEntries); -  // FIXME: Build an actual bitmap -  if (auto EC = PublicsWriter.writeBytes(makeArrayRef(BitmapData))) -    return EC; - -  // FIXME: Write actual hash buckets. -  return Error::success(); -} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp index 9e9ebd11495b..2d8d04ceca4d 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/SymbolStream.cpp @@ -10,11 +10,8 @@  #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"  #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h"  #include "llvm/DebugInfo/MSF/MappedBlockStream.h" -#include "llvm/DebugInfo/PDB/Native/PDBFile.h" -#include "llvm/DebugInfo/PDB/Native/RawConstants.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/Support/BinaryStreamReader.h"  #include "llvm/Support/Endian.h" @@ -43,3 +40,7 @@ SymbolStream::getSymbols(bool *HadError) const {  }  Error SymbolStream::commit() { return Error::success(); } + +codeview::CVSymbol SymbolStream::readRecord(uint32_t Offset) const { +  return *SymbolRecords.at(Offset); +} diff --git a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 9e943c7f114d..8dd30018028e 100644 --- a/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/contrib/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -17,7 +17,6 @@  #include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h"  #include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/DebugInfo/PDB/Native/TpiStream.h"  #include "llvm/Support/Allocator.h"  #include "llvm/Support/BinaryByteStream.h"  #include "llvm/Support/BinaryStreamArray.h"  | 
