[llvm] [Profile] Add a more descriptive message to the bad_header error (PR #211281)

Wael Yehia via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 07:39:33 PDT 2026


https://github.com/w2yehia updated https://github.com/llvm/llvm-project/pull/211281

>From de96c8200206432b63db70fdcda1a7e9e5c3efe2 Mon Sep 17 00:00:00 2001
From: Wael Yehia <wyehia at ca.ibm.com>
Date: Wed, 22 Jul 2026 03:43:48 +0000
Subject: [PATCH 1/2] [Profile] Add a more descriptive message to the
 bad_header error

---
 llvm/lib/ProfileData/InstrProfReader.cpp      | 33 ++++++++++++--
 .../insufficient-binary-ids-size.test         | 20 ++++++---
 .../misaligned-binary-ids-size.test           |  2 +-
 .../raw-magic-but-no-header.test              |  2 +-
 .../llvm-profdata/truncated-profile.test      | 44 +++++++++++++++++++
 5 files changed, 90 insertions(+), 11 deletions(-)
 create mode 100644 llvm/test/tools/llvm-profdata/truncated-profile.test

diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 05770f83ed160..444ac90768d48 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -513,7 +513,8 @@ Error RawInstrProfReader<IntPtrT>::readHeader() {
   if (!hasFormat(*DataBuffer))
     return error(instrprof_error::bad_magic);
   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
-    return error(instrprof_error::bad_header);
+    return error(instrprof_error::bad_header,
+                 std::string("Profile file header is truncated"));
   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
       DataBuffer->getBufferStart());
   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
@@ -597,7 +598,10 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
   const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
   const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
   if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd)
-    return error(instrprof_error::bad_header);
+    return error(instrprof_error::bad_header,
+                 ("BinaryIdSize (" + Twine(BinaryIdSize) +
+                  ") is not a multiple of 8 or the profile is truncated")
+                     .str());
   ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize);
   if (!BinaryIdsBuffer.empty()) {
     if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer,
@@ -650,7 +654,25 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
 
   auto *Start = reinterpret_cast<const char *>(&Header);
   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
-    return error(instrprof_error::bad_header);
+    return error(
+        instrprof_error::bad_header,
+        ("Profile file size (" + Twine(DataBuffer->getBufferSize()) +
+         " bytes) smaller than expected (at least " + Twine(ValueDataOffset) +
+         " bytes = " +
+         Twine(BinaryIdSize) + "(BinaryIdSize) + " +
+         Twine(DataSize) + "(DataSize) + " +
+         Twine(CountersSize) + "(CountersSize) + " +
+         Twine(NumBitmapBytes) + "(NumBitmapBytes) + " +
+         Twine(UniformCountersSectionSize) + "(UniformCountersSectionSize) + " +
+         Twine(NamesSize) + "(NamesSize) + " +
+         Twine(VTableSectionSize) + "(VTableSectionSize) + " +
+         Twine(VTableNameSize) + "(VTableNameSize) + " +
+         Twine(DataOffset - BinaryIdSize + PaddingBytesBeforeCounters +
+               PaddingBytesAfterCounters + PaddingBytesAfterBitmapBytes +
+               PaddingBytesAfterUniformCounters + PaddingBytesAfterNames +
+               PaddingBytesAfterVTableProfData + PaddingBytesAfterVTableNames) +
+         "(Padding))")
+            .str());
 
   if (BIDFetcher) {
     std::vector<object::BuildID> BinaryIDs;
@@ -1373,7 +1395,10 @@ Error IndexedInstrProfReader::readHeader() {
     uint64_t BinaryIdsSize =
         support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr);
     if (BinaryIdsSize % sizeof(uint64_t))
-      return error(instrprof_error::bad_header);
+      return error(instrprof_error::bad_header,
+                   ("BinaryIdSize (" + Twine(BinaryIdsSize) +
+                    ") is not a multiple of 8")
+                       .str());
     // Set the binary ids start.
     BinaryIdsBuffer = ArrayRef<uint8_t>(Ptr, BinaryIdsSize);
     if (Ptr > (const unsigned char *)DataBuffer->getBufferEnd())
diff --git a/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test b/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
index 66fba4ba495b7..b2ee0d9246735 100644
--- a/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
+++ b/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
@@ -3,12 +3,13 @@
 // TODO: use a builtin version of printf
 UNSUPPORTED: system-zos
 RUN: printf '\201rforpl\377' > %t.profraw
-RUN: printf '\10\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\x0B\0\0\0\0\0\0\0' >> %t.profraw
 // We should fail on this because the data buffer (profraw file) is not long
 // enough to hold this binary IDs size. NOTE that this (combined with the 8-byte
 // alignment requirement for binary IDs size) will ensure we can at least read one
 // 8-byte size if the binary IDs are provided.
-RUN: printf '\8\0\0\0\0\0\0\0' >> %t.profraw
+// BinaryIdSize - set to 8 bytes
+RUN: printf '\x08\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
@@ -17,8 +18,17 @@ RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
-
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// ^^ end of Profile Header ^^
+// Incomplete binary IDs data - only 7 bytes instead of 8
 RUN: printf '\0\0\0\0\0\0\0' >> %t.profraw
 
-// RUN: not llvm-profdata show --binary-ids  %t.profraw 2>&1 | FileCheck %s
-// CHECK: invalid instrumentation profile data (file header is corrupt)
+RUN: not llvm-profdata show --binary-ids  %t.profraw 2>&1 | FileCheck %s
+CHECK: invalid instrumentation profile data (file header is corrupt): BinaryIdSize (8) is not a multiple of 8 or the profile is truncated
diff --git a/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test b/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
index 46be16d8b728b..4214b15575560 100644
--- a/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
+++ b/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
@@ -30,4 +30,4 @@ RUN: printf '\2\2\2\2\2\2\2\2' >> %t.profraw
 RUN: printf '\3\3\3\3\0\0\0\0' >> %t.profraw
 
 // RUN: not llvm-profdata show --binary-ids  %t.profraw 2>&1 | FileCheck %s
-// CHECK: invalid instrumentation profile data (file header is corrupt)
+// CHECK: invalid instrumentation profile data (file header is corrupt): BinaryIdSize (63) is not a multiple of 8 or the profile is truncated
diff --git a/llvm/test/tools/llvm-profdata/raw-magic-but-no-header.test b/llvm/test/tools/llvm-profdata/raw-magic-but-no-header.test
index caec1663a04fd..31e1588eedcff 100644
--- a/llvm/test/tools/llvm-profdata/raw-magic-but-no-header.test
+++ b/llvm/test/tools/llvm-profdata/raw-magic-but-no-header.test
@@ -7,4 +7,4 @@ RUN: not llvm-profdata show %t 2>&1 | FileCheck %s
 RUN: printf '\377lprofr\201' > %t
 RUN: not llvm-profdata show %t 2>&1 | FileCheck %s
 
-CHECK: error: {{.+}}: invalid instrumentation profile data (file header is corrupt)
+CHECK: error: {{.+}}: invalid instrumentation profile data (file header is corrupt): Profile file header is truncated
diff --git a/llvm/test/tools/llvm-profdata/truncated-profile.test b/llvm/test/tools/llvm-profdata/truncated-profile.test
new file mode 100644
index 0000000000000..fc51a21b217c3
--- /dev/null
+++ b/llvm/test/tools/llvm-profdata/truncated-profile.test
@@ -0,0 +1,44 @@
+// Magic
+RUN: printf '\x81rforpl\xff' > %t.profraw
+// Version (11 = 0x0B)
+RUN: printf '\13\0\0\0\0\0\0\0' >> %t.profraw
+// BinaryIdsSize
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NumData
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
+// PaddingBytesBeforeCounters
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NumCounters
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw
+// PaddingBytesAfterCounters
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NumBitmapBytes
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// PaddingBytesAfterBitmapBytes
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NumUniformCounters
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// PaddingBytesAfterUniformCounters
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// UniformCountersDelta
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NamesSize
+RUN: printf '\x10\0\0\0\0\0\0\0' >> %t.profraw
+// CountersDelta
+RUN: printf '\xF8\xFF\xFF\xFF\0\0\0\0' >> %t.profraw
+// BitmapDelta
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// NamesDelta
+RUN: printf '\x58\x87\x00\x10\0\0\0\0' >> %t.profraw
+// NumVTables
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// VNamesSize
+RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
+// ValueKindLast
+RUN: printf '\3\0\0\0\0\0\0\0' >> %t.profraw
+// No Binary Ids
+// Array of __llvm_prof_data goes next but we'll truncate it to 4 bytes 
+RUN: printf '\0\0\0\0' >> %t.profraw
+
+RUN: not llvm-profdata show  %t.profraw 2>&1 | FileCheck %s
+CHECK: invalid instrumentation profile data (file header is corrupt): Profile file size (156 bytes) smaller than expected (at least 248 bytes = 0(BinaryIdSize) + 72(DataSize) + 8(CountersSize) + 0(NumBitmapBytes) + 0(UniformCountersSectionSize) + 16(NamesSize) + 0(VTableSectionSize) + 0(VTableNameSize) + 152(Padding))

>From 089d93a0fbdab747b88764ce2069c54cb29b2d8b Mon Sep 17 00:00:00 2001
From: Wael Yehia <wyehia at ca.ibm.com>
Date: Wed, 12 Aug 2026 14:07:32 +0000
Subject: [PATCH 2/2] address review comments

---
 llvm/lib/ProfileData/InstrProfReader.cpp            | 13 ++++++++-----
 .../llvm-profdata/insufficient-binary-ids-size.test |  2 +-
 .../llvm-profdata/misaligned-binary-ids-size.test   |  2 +-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 444ac90768d48..34a7505d8fc81 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -597,11 +597,14 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
       reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
   const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
   const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
-  if (BinaryIdSize % sizeof(uint64_t) || BinaryIdEnd > BufferEnd)
-    return error(instrprof_error::bad_header,
-                 ("BinaryIdSize (" + Twine(BinaryIdSize) +
-                  ") is not a multiple of 8 or the profile is truncated")
-                     .str());
+  if (BinaryIdSize % sizeof(uint64_t))
+    return error(
+        instrprof_error::bad_header,
+        ("BinaryIdSize (" + Twine(BinaryIdSize) + ") is not a multiple of 8")
+            .str());
+  if (BinaryIdEnd > BufferEnd)
+    return error(instrprof_error::truncated);
+
   ArrayRef<uint8_t> BinaryIdsBuffer(BinaryIdStart, BinaryIdSize);
   if (!BinaryIdsBuffer.empty()) {
     if (Error Err = readBinaryIdsInternal(*DataBuffer, BinaryIdsBuffer,
diff --git a/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test b/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
index b2ee0d9246735..8df89a9ca6cb1 100644
--- a/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
+++ b/llvm/test/tools/llvm-profdata/insufficient-binary-ids-size.test
@@ -31,4 +31,4 @@ RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw
 RUN: printf '\0\0\0\0\0\0\0' >> %t.profraw
 
 RUN: not llvm-profdata show --binary-ids  %t.profraw 2>&1 | FileCheck %s
-CHECK: invalid instrumentation profile data (file header is corrupt): BinaryIdSize (8) is not a multiple of 8 or the profile is truncated
+CHECK: truncated profile data
diff --git a/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test b/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
index 4214b15575560..70662390d5e3b 100644
--- a/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
+++ b/llvm/test/tools/llvm-profdata/misaligned-binary-ids-size.test
@@ -30,4 +30,4 @@ RUN: printf '\2\2\2\2\2\2\2\2' >> %t.profraw
 RUN: printf '\3\3\3\3\0\0\0\0' >> %t.profraw
 
 // RUN: not llvm-profdata show --binary-ids  %t.profraw 2>&1 | FileCheck %s
-// CHECK: invalid instrumentation profile data (file header is corrupt): BinaryIdSize (63) is not a multiple of 8 or the profile is truncated
+// CHECK: invalid instrumentation profile data (file header is corrupt): BinaryIdSize (63) is not a multiple of 8



More information about the llvm-commits mailing list