Enable pdbpagesize to allow support for PDB file sizes > 4GB
Enable the pdbpagesize flag to allow linking of PDB files > 4GB. Also includes a couple small fixes to change to uint64_t to support the larger file sizes. I updated the max file size check in MSFBuilder.cpp to take into account the page size. Differential Revision: https://reviews.llvm.org/D115051
This commit is contained in:
@@ -186,12 +186,6 @@ void parsePDBPageSize(StringRef s) {
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: Remove this once other page sizes work.
|
||||
if (v != 4096) {
|
||||
warn("/pdbpagesize: page sizes != 4096 not yet implemented, ignoring flag");
|
||||
v = 4096;
|
||||
}
|
||||
|
||||
config->pdbPageSize = v;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
# RUN: llvm-pdbutil pdb2yaml %t.pdb | FileCheck --check-prefix=PAGE4096 %s
|
||||
# PAGE4096: BlockSize: 4096
|
||||
|
||||
# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbpagesize:8192 2>&1 \
|
||||
# RUN: | FileCheck --check-prefix=TODO %s
|
||||
# TODO: warning: /pdbpagesize: page sizes != 4096 not yet implemented, ignoring flag
|
||||
# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbpagesize:8192
|
||||
# RUN: llvm-pdbutil pdb2yaml %t.pdb | FileCheck --check-prefix=PAGE8192 %s
|
||||
# PAGE8192: BlockSize: 8192
|
||||
|
||||
# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbpagesize:16384
|
||||
# RUN: llvm-pdbutil pdb2yaml %t.pdb | FileCheck --check-prefix=PAGE16384 %s
|
||||
# PAGE16384: BlockSize: 16384
|
||||
|
||||
# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbpagesize:32768
|
||||
# RUN: llvm-pdbutil pdb2yaml %t.pdb | FileCheck --check-prefix=PAGE32768 %s
|
||||
# PAGE32768: BlockSize: 32768
|
||||
|
||||
@@ -101,6 +101,26 @@ inline bool isValidBlockSize(uint32_t Size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Given the specified block size, returns the maximum possible file size.
|
||||
/// Block Size | Max File Size
|
||||
/// <= 4096 | 4GB
|
||||
/// 8192 | 8GB
|
||||
/// 16384 | 16GB
|
||||
/// 32768 | 32GB
|
||||
/// \p Size - the block size of the MSF
|
||||
inline uint64_t getMaxFileSizeFromBlockSize(uint32_t Size) {
|
||||
switch (Size) {
|
||||
case 8192:
|
||||
return (uint64_t)UINT32_MAX * 2ULL;
|
||||
case 16384:
|
||||
return (uint64_t)UINT32_MAX * 3ULL;
|
||||
case 32768:
|
||||
return (uint64_t)UINT32_MAX * 4ULL;
|
||||
default:
|
||||
return (uint64_t)UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
// Super Block, Fpm0, Fpm1, and Block Map
|
||||
inline uint32_t getMinimumBlockCount() { return 4; }
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@ namespace msf {
|
||||
enum class msf_error_code {
|
||||
unspecified = 1,
|
||||
insufficient_buffer,
|
||||
size_overflow,
|
||||
size_overflow_4096,
|
||||
size_overflow_8192,
|
||||
size_overflow_16384,
|
||||
size_overflow_32768,
|
||||
not_writable,
|
||||
no_stream,
|
||||
invalid_format,
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
uint32_t getStreamByteSize(uint32_t StreamIndex) const override;
|
||||
ArrayRef<support::ulittle32_t>
|
||||
getStreamBlockList(uint32_t StreamIndex) const override;
|
||||
uint32_t getFileSize() const;
|
||||
uint64_t getFileSize() const;
|
||||
|
||||
Expected<ArrayRef<uint8_t>> getBlockData(uint32_t BlockIndex,
|
||||
uint32_t NumBytes) const override;
|
||||
|
||||
@@ -343,15 +343,25 @@ Expected<FileBufferByteStream> MSFBuilder::commit(StringRef Path,
|
||||
Layout = std::move(*L);
|
||||
|
||||
uint64_t FileSize = uint64_t(Layout.SB->BlockSize) * Layout.SB->NumBlocks;
|
||||
if (FileSize > UINT32_MAX) {
|
||||
// FIXME: Changing the BinaryStream classes to use 64-bit numbers lets
|
||||
// us create PDBs larger than 4 GiB successfully. The file format is
|
||||
// block-based and as long as each stream is small enough, PDBs larger than
|
||||
// 4 GiB might work. Check if tools can handle these large PDBs, and if so
|
||||
// add support for writing them.
|
||||
// Ensure that the file size is under the limit for the specified block size.
|
||||
if (FileSize > getMaxFileSizeFromBlockSize(Layout.SB->BlockSize)) {
|
||||
msf_error_code error_code;
|
||||
switch (Layout.SB->BlockSize) {
|
||||
case 8192:
|
||||
error_code = msf_error_code::size_overflow_8192;
|
||||
case 16384:
|
||||
error_code = msf_error_code::size_overflow_16384;
|
||||
case 32768:
|
||||
error_code = msf_error_code::size_overflow_32768;
|
||||
default:
|
||||
error_code = msf_error_code::size_overflow_4096;
|
||||
}
|
||||
|
||||
return make_error<MSFError>(
|
||||
msf_error_code::size_overflow,
|
||||
formatv("File size would have been {0,1:N}", FileSize));
|
||||
error_code,
|
||||
formatv("File size would have been {0,1:N} which exceeds the maximum \
|
||||
file size for the current page size {1}",
|
||||
FileSize, Layout.SB->BlockSize));
|
||||
}
|
||||
|
||||
auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
|
||||
|
||||
@@ -28,8 +28,14 @@ public:
|
||||
case msf_error_code::insufficient_buffer:
|
||||
return "The buffer is not large enough to read the requested number of "
|
||||
"bytes.";
|
||||
case msf_error_code::size_overflow:
|
||||
case msf_error_code::size_overflow_4096:
|
||||
return "Output data is larger than 4 GiB.";
|
||||
case msf_error_code::size_overflow_8192:
|
||||
return "Output data is larger than 8 GiB.";
|
||||
case msf_error_code::size_overflow_16384:
|
||||
return "Output data is larger than 16 GiB.";
|
||||
case msf_error_code::size_overflow_32768:
|
||||
return "Output data is larger than 32 GiB.";
|
||||
case msf_error_code::not_writable:
|
||||
return "The specified stream is not writable.";
|
||||
case msf_error_code::no_stream:
|
||||
|
||||
@@ -100,7 +100,7 @@ PDBFile::getStreamBlockList(uint32_t StreamIndex) const {
|
||||
return ContainerLayout.StreamMap[StreamIndex];
|
||||
}
|
||||
|
||||
uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); }
|
||||
uint64_t PDBFile::getFileSize() const { return Buffer->getLength(); }
|
||||
|
||||
Expected<ArrayRef<uint8_t>> PDBFile::getBlockData(uint32_t BlockIndex,
|
||||
uint32_t NumBytes) const {
|
||||
|
||||
@@ -40,7 +40,7 @@ struct MSFHeaders {
|
||||
uint32_t NumDirectoryBlocks = 0;
|
||||
std::vector<uint32_t> DirectoryBlocks;
|
||||
uint32_t NumStreams = 0;
|
||||
uint32_t FileSize = 0;
|
||||
uint64_t FileSize = 0;
|
||||
};
|
||||
|
||||
struct StreamBlockList {
|
||||
|
||||
Reference in New Issue
Block a user