return readHeader(*Header);
}
+template <class IntPtrT>
+error_code RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
+ const char *End = DataBuffer->getBufferEnd();
+ // Skip zero padding between profiles.
+ while (CurrentPos != End && *CurrentPos == 0)
+ ++CurrentPos;
+ // If there's nothing left, we're done.
+ if (CurrentPos == End)
+ return instrprof_error::eof;
+ // If there isn't enough space for another header, this is probably just
+ // garbage at the end of the file.
+ if (CurrentPos + sizeof(RawHeader) > End)
+ return instrprof_error::malformed;
+ // The magic should have the same byte order as in the previous header.
+ uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
+ if (Magic != swap(getRawMagic<IntPtrT>()))
+ return instrprof_error::bad_magic;
+
+ // There's another profile to read, so we need to process the header.
+ auto *Header = reinterpret_cast<const RawHeader *>(CurrentPos);
+ return readHeader(*Header);
+}
+
static uint64_t getRawVersion() {
return 1;
}
ptrdiff_t DataOffset = sizeof(RawHeader);
ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize;
ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
- size_t FileSize = NamesOffset + sizeof(char) * NamesSize;
+ size_t ProfileSize = NamesOffset + sizeof(char) * NamesSize;
- if (FileSize != DataBuffer->getBufferSize())
+ auto *Start = reinterpret_cast<const char *>(&Header);
+ if (Start + ProfileSize > DataBuffer->getBufferEnd())
return error(instrprof_error::bad_header);
- const char *Start = DataBuffer->getBufferStart();
Data = reinterpret_cast<const ProfileData *>(Start + DataOffset);
DataEnd = Data + DataSize;
CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
NamesStart = Start + NamesOffset;
+ ProfileEnd = Start + ProfileSize;
return success();
}
error_code
RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
if (Data == DataEnd)
- return error(instrprof_error::eof);
+ if (error_code EC = readNextHeader(ProfileEnd))
+ return EC;
// Get the raw data.
StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize));
--- /dev/null
+RUN: printf '\201rforpl\377' > %t-foo.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf '\3\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw
+RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw
+
+RUN: printf '\3\0\0\0' >> %t-foo.profraw
+RUN: printf '\1\0\0\0' >> %t-foo.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw
+RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw
+
+RUN: printf '\023\0\0\0\0\0\0\0' >> %t-foo.profraw
+RUN: printf 'foo' >> %t-foo.profraw
+
+RUN: printf '\201rforpl\377' > %t-bar.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\3\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw
+RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw
+
+RUN: printf '\3\0\0\0' >> %t-bar.profraw
+RUN: printf '\2\0\0\0' >> %t-bar.profraw
+RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw
+RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw
+
+RUN: printf '\067\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf '\101\0\0\0\0\0\0\0' >> %t-bar.profraw
+RUN: printf 'bar' >> %t-bar.profraw
+
+Versions of the profiles that are padded to eight byte alignment.
+RUN: cat %t-foo.profraw > %t-foo-padded.profraw
+RUN: printf '\0\0\0\0\0' >> %t-foo-padded.profraw
+RUN: cat %t-bar.profraw > %t-bar-padded.profraw
+RUN: printf '\0\0\0\0\0' >> %t-bar-padded.profraw
+
+RUN: cat %t-foo.profraw %t-bar.profraw > %t-nopad.profraw
+RUN: cat %t-foo-padded.profraw %t-bar.profraw > %t-pad-between.profraw
+RUN: cat %t-foo-padded.profraw %t-bar-padded.profraw > %t-pad.profraw
+
+RUN: llvm-profdata show %t-nopad.profraw -all-functions -counts | FileCheck %s
+RUN: llvm-profdata show %t-pad-between.profraw -all-functions -counts | FileCheck %s
+RUN: llvm-profdata show %t-pad.profraw -all-functions -counts | FileCheck %s
+
+CHECK: Counters:
+CHECK: foo:
+CHECK: Hash: 0x0000000000000001
+CHECK: Counters: 1
+CHECK: Function count: 19
+CHECK: Block counts: []
+CHECK: bar:
+CHECK: Hash: 0x0000000000000002
+CHECK: Counters: 2
+CHECK: Function count: 55
+CHECK: Block counts: [65]
+CHECK: Functions shown: 2
+CHECK: Total functions: 2
+CHECK: Maximum function count: 55
+CHECK: Maximum internal block count: 65