[lld/pdb] Create an empty public symbol record stream.

This is part of the continuing effort to increase parity between
LLD and MSVC PDBs.  link still doesn't like our PDBs, so the most
obvious thing to check was whether adding an empty publics stream
would get it to do something else.  It still fails in the same way
but at least this removes one more variable from the equation.
The next logical step would be to try creating an empty globals
stream.

Differential Revision: https://reviews.llvm.org/D35224

llvm-svn: 307598
This commit is contained in:
Zachary Turner 2017-07-10 22:40:20 +00:00
parent 7466ccfc59
commit 7eaf1d96ad
12 changed files with 217 additions and 26 deletions

View File

@ -481,6 +481,13 @@ void coff::createPDB(SymbolTable *Symtab, ArrayRef<uint8_t> SectionTable,
TypeTableBuilder IDTable(BAlloc);
addObjectsToPDB(Alloc, Symtab, Builder, TypeTable, IDTable);
// Add public and symbol records stream.
// For now we don't actually write any thing useful to the publics stream, but
// the act of "getting" it also creates it lazily so that we write an empty
// stream.
(void)Builder.getPublicsBuilder();
// Add Section Contributions.
addSectionContribs(Symtab, DbiBuilder);

View File

@ -53,12 +53,12 @@ CHECK-NEXT: | TPI Hash | {{[EI]}} |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | IPI Hash | {{[EI]}} |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | Public Symbol Hash | {{[EI]}} |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | Public Symbol Records | {{[EI]}} |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | Global Symbol Hash | D |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | Public Symbol Hash | D |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: | Public Symbol Records | D |
CHECK-NEXT: |------------------------------+---|
CHECK-NEXT: ------------------------------------
CHECK-NEXT: | String Table |
CHECK-NEXT: |------------------------------+---|
@ -154,9 +154,9 @@ CHECK-NEXT: | DBG (SectionHdrOrig) | I |
CHECK-NEXT: |----------------------------------------+---|
CHECK-NEXT: | Globals Stream | D |
CHECK-NEXT: |----------------------------------------+---|
CHECK-NEXT: | Publics Stream | D |
CHECK-NEXT: | Publics Stream | {{[EI]}} |
CHECK-NEXT: |----------------------------------------+---|
CHECK-NEXT: | Symbol Records | D |
CHECK-NEXT: | Symbol Records | {{[EI]}} |
CHECK-NEXT: |----------------------------------------+---|
CHECK-NEXT: | Has CTypes | I |
CHECK-NEXT: |----------------------------------------+---|

View File

@ -59,6 +59,9 @@ public:
uint32_t calculateSerializedLength() const;
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(StringRef Module, StringRef File);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
@ -90,7 +93,6 @@ private:
uint32_t calculateNamesBufferSize() const;
uint32_t calculateDbgStreamsSize() const;
Error generateModiSubstream();
Error generateFileInfoSubstream();
msf::MSFBuilder &Msf;
@ -103,6 +105,8 @@ private:
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
uint32_t PublicsStreamIndex = kInvalidStreamIndex;
uint32_t SymRecordStreamIndex = kInvalidStreamIndex;
const DbiStreamHeader *Header;

View File

@ -31,11 +31,13 @@ class MSFBuilder;
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
class PublicsStreamBuilder;
class TpiStreamBuilder;
class PDBFileBuilder {
public:
explicit PDBFileBuilder(BumpPtrAllocator &Allocator);
~PDBFileBuilder();
PDBFileBuilder(const PDBFileBuilder &) = delete;
PDBFileBuilder &operator=(const PDBFileBuilder &) = delete;
@ -47,6 +49,7 @@ public:
TpiStreamBuilder &getTpiBuilder();
TpiStreamBuilder &getIpiBuilder();
PDBStringTableBuilder &getStringTableBuilder();
PublicsStreamBuilder &getPublicsBuilder();
Error commit(StringRef Filename);
@ -61,6 +64,7 @@ private:
std::unique_ptr<msf::MSFBuilder> Msf;
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
std::unique_ptr<PublicsStreamBuilder> Publics;
std::unique_ptr<TpiStreamBuilder> Tpi;
std::unique_ptr<TpiStreamBuilder> Ipi;

View File

@ -25,8 +25,6 @@ struct GSIHashHeader;
class PDBFile;
class PublicsStream {
struct HeaderInfo;
public:
PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
~PublicsStream();
@ -65,7 +63,7 @@ private:
FixedStreamArray<support::ulittle32_t> ThunkMap;
FixedStreamArray<SectionOffset> SectionOffsets;
const HeaderInfo *Header;
const PublicsStreamHeader *Header;
const GSIHashHeader *HashHdr;
};
}

View File

@ -0,0 +1,54 @@
//===- PublicsStreamBuilder.h - PDB Publics Stream Creation -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace msf {
class MSFBuilder;
}
namespace pdb {
class PublicsStream;
struct PublicsStreamHeader;
class PublicsStreamBuilder {
public:
explicit PublicsStreamBuilder(msf::MSFBuilder &Msf);
~PublicsStreamBuilder();
PublicsStreamBuilder(const PublicsStreamBuilder &) = delete;
PublicsStreamBuilder &operator=(const PublicsStreamBuilder &) = delete;
Error finalizeMsfLayout();
uint32_t calculateSerializedLength() const;
Error commit(BinaryStreamWriter &PublicsWriter);
uint32_t getStreamIndex() const { return StreamIdx; }
uint32_t getRecordStreamIdx() const { return RecordStreamIdx; }
private:
uint32_t StreamIdx = kInvalidStreamIndex;
uint32_t RecordStreamIdx = kInvalidStreamIndex;
std::vector<PSHashRecord> HashRecords;
msf::MSFBuilder &Msf;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -255,6 +255,19 @@ struct ModuleInfoHeader {
/// char ObjFileName[];
};
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStreamHeader {
support::ulittle32_t SymHash;
support::ulittle32_t AddrMap;
support::ulittle32_t NumThunks;
support::ulittle32_t SizeOfThunk;
support::ulittle16_t ISectThunkTable;
char Padding[2];
support::ulittle32_t OffThunkTable;
support::ulittle32_t NumSections;
};
/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but
/// is abstracted here for the purposes of non-Windows platforms that don't have
/// the GUID structure defined.

View File

@ -53,6 +53,7 @@ add_pdb_impl_folder(Native
Native/PDBStringTableBuilder.cpp
Native/PDBTypeServerHandler.cpp
Native/PublicsStream.cpp
Native/PublicsStreamBuilder.cpp
Native/RawError.cpp
Native/SymbolStream.cpp
Native/TpiHashing.cpp

View File

@ -49,6 +49,14 @@ void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
SectionMap = SecMap;
}
void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) {
SymRecordStreamIndex = Index;
}
void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
PublicsStreamIndex = Index;
}
Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
ArrayRef<uint8_t> Data) {
if (DbgStreams[(int)Type].StreamNumber != kInvalidStreamIndex)
@ -259,8 +267,8 @@ Error DbiStreamBuilder::finalize() {
H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
H->SectionMapSize = calculateSectionMapStreamSize();
H->TypeServerSize = 0;
H->SymRecordStreamIndex = kInvalidStreamIndex;
H->PublicSymbolStreamIndex = kInvalidStreamIndex;
H->SymRecordStreamIndex = SymRecordStreamIndex;
H->PublicSymbolStreamIndex = PublicsStreamIndex;
H->MFCTypeServerIndex = kInvalidStreamIndex;
H->GlobalSymbolStreamIndex = kInvalidStreamIndex;

View File

@ -18,6 +18,7 @@
#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"
@ -33,6 +34,8 @@ using namespace llvm::support;
PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
: Allocator(Allocator) {}
PDBFileBuilder::~PDBFileBuilder() {}
Error PDBFileBuilder::initialize(uint32_t BlockSize) {
auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
if (!ExpectedMsf)
@ -71,6 +74,12 @@ PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
return Strings;
}
PublicsStreamBuilder &PDBFileBuilder::getPublicsBuilder() {
if (!Publics)
Publics = llvm::make_unique<PublicsStreamBuilder>(*Msf);
return *Publics;
}
Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
auto ExpectedStream = Msf->addStream(Size);
if (!ExpectedStream)
@ -113,6 +122,14 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
if (auto EC = Ipi->finalizeMsfLayout())
return std::move(EC);
}
if (Publics) {
if (auto EC = Publics->finalizeMsfLayout())
return std::move(EC);
if (Dbi) {
Dbi->setPublicsStreamIndex(Publics->getStreamIndex());
Dbi->setSymbolRecordStreamIndex(Publics->getRecordStreamIdx());
}
}
return Msf->build();
}
@ -192,5 +209,13 @@ 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))
return EC;
}
return Buffer.commit();
}

View File

@ -41,19 +41,6 @@ using namespace llvm::msf;
using namespace llvm::support;
using namespace llvm::pdb;
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStream::HeaderInfo {
ulittle32_t SymHash;
ulittle32_t AddrMap;
ulittle32_t NumThunks;
ulittle32_t SizeOfThunk;
ulittle16_t ISectThunkTable;
char Padding[2];
ulittle32_t OffThunkTable;
ulittle32_t NumSections;
};
PublicsStream::PublicsStream(PDBFile &File,
std::unique_ptr<MappedBlockStream> Stream)
: Pdb(File), Stream(std::move(Stream)) {}
@ -72,7 +59,8 @@ Error PublicsStream::reload() {
BinaryStreamReader Reader(*Stream);
// Check stream size.
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
if (Reader.bytesRemaining() <
sizeof(PublicsStreamHeader) + sizeof(GSIHashHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");

View File

@ -0,0 +1,89 @@
//===- 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();
}