Make PDBFile store an msf::Layout.

Previously it was storing all the fields of an msf::Layout as
separate members.  This is a trivial cleanup to make it store
an msf::Layout directly.  This makes the code more readable
since it becomes clear which fields of PDBFile are actually the
msf specific layout information in a sea of other bookkeeping
fields.

llvm-svn: 276460
This commit is contained in:
Zachary Turner 2016-07-22 19:56:33 +00:00
parent e109dc63f9
commit e4a4f33daf
5 changed files with 62 additions and 63 deletions

View File

@ -49,7 +49,8 @@ struct SuperBlock {
};
struct Layout {
SuperBlock *SB;
Layout() : SB(nullptr) {}
const SuperBlock *SB;
ArrayRef<support::ulittle32_t> DirectoryBlocks;
ArrayRef<support::ulittle32_t> StreamSizes;
std::vector<ArrayRef<support::ulittle32_t>> StreamMap;

View File

@ -67,9 +67,11 @@ public:
Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
ArrayRef<uint8_t> Data) const override;
ArrayRef<support::ulittle32_t> getStreamSizes() const { return StreamSizes; }
ArrayRef<support::ulittle32_t> getStreamSizes() const {
return MsfLayout.StreamSizes;
}
ArrayRef<ArrayRef<support::ulittle32_t>> getStreamMap() const {
return StreamMap;
return MsfLayout.StreamMap;
}
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
@ -88,15 +90,11 @@ public:
Error commit();
private:
Error setSuperBlock(const msf::SuperBlock *Block);
BumpPtrAllocator &Allocator;
std::unique_ptr<msf::StreamInterface> Buffer;
const msf::SuperBlock *SB;
ArrayRef<support::ulittle32_t> StreamSizes;
ArrayRef<support::ulittle32_t> DirectoryBlocks;
std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
msf::Layout MsfLayout;
std::unique_ptr<InfoStream> Info;
std::unique_ptr<DbiStream> Dbi;

View File

@ -219,17 +219,18 @@ uint32_t MsfBuilder::computeDirectoryByteSize() const {
}
Expected<Layout> MsfBuilder::build() {
SuperBlock *SB = Allocator.Allocate<SuperBlock>();
Layout L;
L.SB = Allocator.Allocate<SuperBlock>();
std::memcpy(L.SB->MagicBytes, Magic, sizeof(Magic));
L.SB->BlockMapAddr = BlockMapAddr;
L.SB->BlockSize = BlockSize;
L.SB->NumDirectoryBytes = computeDirectoryByteSize();
L.SB->FreeBlockMapBlock = FreePageMap;
L.SB->Unknown1 = Unknown1;
L.SB = SB;
uint32_t NumDirectoryBlocks =
bytesToBlocks(L.SB->NumDirectoryBytes, BlockSize);
std::memcpy(SB->MagicBytes, Magic, sizeof(Magic));
SB->BlockMapAddr = BlockMapAddr;
SB->BlockSize = BlockSize;
SB->NumDirectoryBytes = computeDirectoryByteSize();
SB->FreeBlockMapBlock = FreePageMap;
SB->Unknown1 = Unknown1;
uint32_t NumDirectoryBlocks = bytesToBlocks(SB->NumDirectoryBytes, BlockSize);
if (NumDirectoryBlocks > DirectoryBlocks.size()) {
// Our hint wasn't enough to satisfy the entire directory. Allocate
// remaining pages.
@ -251,7 +252,7 @@ Expected<Layout> MsfBuilder::build() {
// Don't set the number of blocks in the file until after allocating Blocks
// for the directory, since the allocation might cause the file to need to
// grow.
L.SB->NumBlocks = FreeBlocks.size();
SB->NumBlocks = FreeBlocks.size();
ulittle32_t *DirBlocks = Allocator.Allocate<ulittle32_t>(NumDirectoryBlocks);
std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,

View File

@ -38,39 +38,46 @@ typedef FixedStreamArray<support::ulittle32_t> ulittle_array;
PDBFile::PDBFile(std::unique_ptr<StreamInterface> PdbFileBuffer,
BumpPtrAllocator &Allocator)
: Allocator(Allocator), Buffer(std::move(PdbFileBuffer)), SB(nullptr) {}
: Allocator(Allocator), Buffer(std::move(PdbFileBuffer)) {}
PDBFile::~PDBFile() {}
uint32_t PDBFile::getBlockSize() const { return SB->BlockSize; }
uint32_t PDBFile::getBlockSize() const { return MsfLayout.SB->BlockSize; }
uint32_t PDBFile::getFreeBlockMapBlock() const { return SB->FreeBlockMapBlock; }
uint32_t PDBFile::getFreeBlockMapBlock() const {
return MsfLayout.SB->FreeBlockMapBlock;
}
uint32_t PDBFile::getBlockCount() const { return SB->NumBlocks; }
uint32_t PDBFile::getBlockCount() const { return MsfLayout.SB->NumBlocks; }
uint32_t PDBFile::getNumDirectoryBytes() const { return SB->NumDirectoryBytes; }
uint32_t PDBFile::getNumDirectoryBytes() const {
return MsfLayout.SB->NumDirectoryBytes;
}
uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; }
uint32_t PDBFile::getBlockMapIndex() const {
return MsfLayout.SB->BlockMapAddr;
}
uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; }
uint32_t PDBFile::getUnknown1() const { return MsfLayout.SB->Unknown1; }
uint32_t PDBFile::getNumDirectoryBlocks() const {
return msf::bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize);
return msf::bytesToBlocks(MsfLayout.SB->NumDirectoryBytes,
MsfLayout.SB->BlockSize);
}
uint64_t PDBFile::getBlockMapOffset() const {
return (uint64_t)SB->BlockMapAddr * SB->BlockSize;
return (uint64_t)MsfLayout.SB->BlockMapAddr * MsfLayout.SB->BlockSize;
}
uint32_t PDBFile::getNumStreams() const { return StreamSizes.size(); }
uint32_t PDBFile::getNumStreams() const { return MsfLayout.StreamSizes.size(); }
uint32_t PDBFile::getStreamByteSize(uint32_t StreamIndex) const {
return StreamSizes[StreamIndex];
return MsfLayout.StreamSizes[StreamIndex];
}
ArrayRef<support::ulittle32_t>
PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
return StreamMap[StreamIndex];
return MsfLayout.StreamMap[StreamIndex];
}
uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
@ -104,24 +111,31 @@ Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset,
Error PDBFile::parseFileHeaders() {
StreamReader Reader(*Buffer);
const msf::SuperBlock *SB = nullptr;
if (auto EC = Reader.readObject(SB)) {
consumeError(std::move(EC));
return make_error<RawError>(raw_error_code::corrupt_file,
"Does not contain superblock");
}
if (auto EC = setSuperBlock(SB))
if (auto EC = msf::validateSuperBlock(*SB))
return EC;
if (Buffer->getLength() % SB->BlockSize != 0)
return make_error<RawError>(raw_error_code::corrupt_file,
"File size is not a multiple of block size");
MsfLayout.SB = SB;
Reader.setOffset(getBlockMapOffset());
if (auto EC = Reader.readArray(DirectoryBlocks, getNumDirectoryBlocks()))
if (auto EC =
Reader.readArray(MsfLayout.DirectoryBlocks, getNumDirectoryBlocks()))
return EC;
return Error::success();
}
Error PDBFile::parseStreamData() {
assert(SB);
assert(MsfLayout.SB);
if (DirectoryStream)
return Error::success();
@ -133,21 +147,22 @@ Error PDBFile::parseStreamData() {
// subclass of IPDBStreamData which only accesses the fields that have already
// been parsed, we can avoid this and reuse MappedBlockStream.
auto DS = MappedBlockStream::createDirectoryStream(
SB->NumDirectoryBytes, getDirectoryBlockArray(), *this);
MsfLayout.SB->NumDirectoryBytes, getDirectoryBlockArray(), *this);
if (!DS)
return DS.takeError();
StreamReader Reader(**DS);
if (auto EC = Reader.readInteger(NumStreams))
return EC;
if (auto EC = Reader.readArray(StreamSizes, NumStreams))
if (auto EC = Reader.readArray(MsfLayout.StreamSizes, NumStreams))
return EC;
for (uint32_t I = 0; I < NumStreams; ++I) {
uint32_t StreamSize = getStreamByteSize(I);
// FIXME: What does StreamSize ~0U mean?
uint64_t NumExpectedStreamBlocks =
StreamSize == UINT32_MAX ? 0 : msf::bytesToBlocks(StreamSize,
SB->BlockSize);
StreamSize == UINT32_MAX
? 0
: msf::bytesToBlocks(StreamSize, MsfLayout.SB->BlockSize);
// For convenience, we store the block array contiguously. This is because
// if someone calls setStreamMap(), it is more convenient to be able to call
@ -159,12 +174,12 @@ Error PDBFile::parseStreamData() {
if (auto EC = Reader.readArray(Blocks, NumExpectedStreamBlocks))
return EC;
for (uint32_t Block : Blocks) {
uint64_t BlockEndOffset = (uint64_t)(Block + 1) * SB->BlockSize;
uint64_t BlockEndOffset = (uint64_t)(Block + 1) * MsfLayout.SB->BlockSize;
if (BlockEndOffset > getFileSize())
return make_error<RawError>(raw_error_code::corrupt_file,
"Stream block map is corrupt.");
}
StreamMap.push_back(Blocks);
MsfLayout.StreamMap.push_back(Blocks);
}
// We should have read exactly SB->NumDirectoryBytes bytes.
@ -174,7 +189,7 @@ Error PDBFile::parseStreamData() {
}
llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() const {
return DirectoryBlocks;
return MsfLayout.DirectoryBlocks;
}
Expected<InfoStream &> PDBFile::getPDBInfoStream() {
@ -297,29 +312,17 @@ Expected<NameHashTable &> PDBFile::getStringTable() {
return *StringTable;
}
Error PDBFile::setSuperBlock(const msf::SuperBlock *Block) {
if (auto EC = msf::validateSuperBlock(*Block))
return EC;
if (Buffer->getLength() % SB->BlockSize != 0)
return make_error<RawError>(raw_error_code::corrupt_file,
"File size is not a multiple of block size");
SB = Block;
return Error::success();
}
Error PDBFile::commit() {
StreamWriter Writer(*Buffer);
if (auto EC = Writer.writeObject(*SB))
if (auto EC = Writer.writeObject(*MsfLayout.SB))
return EC;
Writer.setOffset(getBlockMapOffset());
if (auto EC = Writer.writeArray(DirectoryBlocks))
if (auto EC = Writer.writeArray(MsfLayout.DirectoryBlocks))
return EC;
auto DS = MappedBlockStream::createDirectoryStream(
SB->NumDirectoryBytes, getDirectoryBlockArray(), *this);
MsfLayout.SB->NumDirectoryBytes, getDirectoryBlockArray(), *this);
if (!DS)
return DS.takeError();
auto DirStream = std::move(*DS);
@ -327,10 +330,10 @@ Error PDBFile::commit() {
if (auto EC = DW.writeInteger(this->getNumStreams()))
return EC;
if (auto EC = DW.writeArray(StreamSizes))
if (auto EC = DW.writeArray(MsfLayout.StreamSizes))
return EC;
for (const auto &Blocks : StreamMap) {
for (const auto &Blocks : MsfLayout.StreamMap) {
if (auto EC = DW.writeArray(Blocks))
return EC;
}

View File

@ -76,11 +76,7 @@ PDBFileBuilder::build(std::unique_ptr<msf::StreamInterface> PdbFileBuffer) {
return ExpectedLayout.takeError();
auto File = llvm::make_unique<PDBFile>(std::move(PdbFileBuffer), Allocator);
const msf::Layout &L = *ExpectedLayout;
File->StreamMap = L.StreamMap;
File->StreamSizes = L.StreamSizes;
File->DirectoryBlocks = L.DirectoryBlocks;
File->SB = L.SB;
File->MsfLayout = *ExpectedLayout;
if (Info) {
auto ExpectedInfo = Info->build(*File);