[llvm] 724b58f - [PDB] Error on too large stream directories

Hans Wennborg via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 24 06:12:24 PST 2023


Author: Hans Wennborg
Date: 2023-02-24T15:07:11+01:00
New Revision: 724b58f76691e5633fc9e2e19d64e476b0c7845e

URL: https://github.com/llvm/llvm-project/commit/724b58f76691e5633fc9e2e19d64e476b0c7845e
DIFF: https://github.com/llvm/llvm-project/commit/724b58f76691e5633fc9e2e19d64e476b0c7845e.diff

LOG: [PDB] Error on too large stream directories

We hit this in Chromium builds where the PDB file was just under 4GB,
but the stream directory was actually too large to be correctly
represented.

llvm-pdbutil would error about this in llvm::msf::validateSuperBlock,
but lld should not write such PDB files in the first place.

Differential revision: https://reviews.llvm.org/D144385

Added: 
    

Modified: 
    lld/COFF/PDB.cpp
    llvm/include/llvm/DebugInfo/MSF/MSFError.h
    llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
    llvm/lib/DebugInfo/MSF/MSFError.cpp

Removed: 
    


################################################################################
diff  --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp
index 745afab12e82c..94af920d5e7a1 100644
--- a/lld/COFF/PDB.cpp
+++ b/lld/COFF/PDB.cpp
@@ -31,6 +31,7 @@
 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
 #include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/DebugInfo/MSF/MSFError.h"
 #include "llvm/DebugInfo/PDB/GenericError.h"
 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
@@ -1687,6 +1688,12 @@ void PDBLinker::commit(codeview::GUID *guid) {
   // the user can see the output of /time and /summary, which is very helpful
   // when trying to figure out why a PDB file is too large.
   if (Error e = builder.commit(ctx.config.pdbPath, guid)) {
+    e = handleErrors(std::move(e),
+        [](const llvm::msf::MSFError &me) {
+          error(me.message());
+          if (me.isPageOverflow())
+            error("try setting a larger /pdbpagesize");
+        });
     checkError(std::move(e));
     error("failed to write PDB file " + Twine(ctx.config.pdbPath));
   }

diff  --git a/llvm/include/llvm/DebugInfo/MSF/MSFError.h b/llvm/include/llvm/DebugInfo/MSF/MSFError.h
index b84f9d7c4feef..88c823f603cf5 100644
--- a/llvm/include/llvm/DebugInfo/MSF/MSFError.h
+++ b/llvm/include/llvm/DebugInfo/MSF/MSFError.h
@@ -16,14 +16,15 @@ namespace msf {
 enum class msf_error_code {
   unspecified = 1,
   insufficient_buffer,
+  not_writable,
+  no_stream,
+  invalid_format,
+  block_in_use,
   size_overflow_4096,
   size_overflow_8192,
   size_overflow_16384,
   size_overflow_32768,
-  not_writable,
-  no_stream,
-  invalid_format,
-  block_in_use
+  stream_directory_overflow,
 };
 } // namespace msf
 } // namespace llvm
@@ -46,6 +47,25 @@ class MSFError : public ErrorInfo<MSFError, StringError> {
 public:
   using ErrorInfo<MSFError, StringError>::ErrorInfo; // inherit constructors
   MSFError(const Twine &S) : ErrorInfo(S, msf_error_code::unspecified) {}
+
+  bool isPageOverflow() const {
+    switch (static_cast<msf_error_code>(convertToErrorCode().value())) {
+    case msf_error_code::unspecified:
+    case msf_error_code::insufficient_buffer:
+    case msf_error_code::not_writable:
+    case msf_error_code::no_stream:
+    case msf_error_code::invalid_format:
+    case msf_error_code::block_in_use:
+      return false;
+    case msf_error_code::size_overflow_4096:
+    case msf_error_code::size_overflow_8192:
+    case msf_error_code::size_overflow_16384:
+    case msf_error_code::size_overflow_32768:
+    case msf_error_code::stream_directory_overflow:
+      return true;
+    }
+  }
+
   static char ID;
 };
 } // namespace msf

diff  --git a/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp b/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
index f9a763d724a85..c26caa647ed9f 100644
--- a/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
+++ b/llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
@@ -364,6 +364,18 @@ Expected<FileBufferByteStream> MSFBuilder::commit(StringRef Path,
                 FileSize, Layout.SB->BlockSize));
   }
 
+  uint64_t NumDirectoryBlocks =
+      bytesToBlocks(Layout.SB->NumDirectoryBytes, Layout.SB->BlockSize);
+  uint64_t DirectoryBlockMapSize =
+      NumDirectoryBlocks * sizeof(support::ulittle32_t);
+  if (DirectoryBlockMapSize > Layout.SB->BlockSize) {
+    return make_error<MSFError>(msf_error_code::stream_directory_overflow,
+                                formatv("The directory block map ({0} bytes) "
+                                        "doesn't fit in a block ({1} bytes)",
+                                        DirectoryBlockMapSize,
+                                        Layout.SB->BlockSize));
+  }
+
   auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
   if (auto EC = OutFileOrError.takeError())
     return std::move(EC);

diff  --git a/llvm/lib/DebugInfo/MSF/MSFError.cpp b/llvm/lib/DebugInfo/MSF/MSFError.cpp
index fd93c3e726ccb..dbd8648c4d41d 100644
--- a/llvm/lib/DebugInfo/MSF/MSFError.cpp
+++ b/llvm/lib/DebugInfo/MSF/MSFError.cpp
@@ -43,6 +43,8 @@ class MSFErrorCategory : public std::error_category {
       return "The data is in an unexpected format.";
     case msf_error_code::block_in_use:
       return "The block is already in use.";
+    case msf_error_code::stream_directory_overflow:
+      return "PDB stream directory too large.";
     }
     llvm_unreachable("Unrecognized msf_error_code");
   }


        


More information about the llvm-commits mailing list